diff --git a/CHANGELOG.md b/CHANGELOG.md index 27486665e4..bc701a3196 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- +## [2.1.1] — 2026-03-09 + +> ### 🔧 CI Fix + Docs Reorganization + +### Bug Fixes + +- **CI: fixed `any`-budget violation in `open-sse/services/usage.ts`** — replaced 5 explicit `any` annotations with proper TypeScript types (`UsageQuota`, `JsonRecord`, `Error`), restoring the green CI lint gate. +- **Deleted all duplicate draft GitHub releases** — automated workflow was creating unnamed draft releases on each push; cleaned up all draft artifacts for v2.0.17–v2.1.0. + +### Documentation + +- **Root cleanup**: moved all 29 `README..md` files from the project root into their correct `docs/i18n//README.md` locations. The root now contains only `README.md` (English). +- **i18n sync**: all 11 `docs/*.md` files synced with language bar headers to all 30 `docs/i18n//` directories (319 file updates across 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). + +--- + ## [2.1.0] — 2026-03-09 > ### 🗺️ Full Provider-UI Gap Audit — All Backends Now Accessible from Dashboard diff --git a/docs/i18n/ar/A2A-SERVER.md b/docs/i18n/ar/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/ar/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/ar/API_REFERENCE.md b/docs/i18n/ar/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/ar/API_REFERENCE.md +++ b/docs/i18n/ar/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/ar/ARCHITECTURE.md b/docs/i18n/ar/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/ar/ARCHITECTURE.md +++ b/docs/i18n/ar/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/ar/AUTO-COMBO.md b/docs/i18n/ar/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/ar/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/ar/CODEBASE_DOCUMENTATION.md b/docs/i18n/ar/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/ar/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ar/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/ar/FEATURES.md b/docs/i18n/ar/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/ar/FEATURES.md +++ b/docs/i18n/ar/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/ar/MCP-SERVER.md b/docs/i18n/ar/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/ar/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.ar.md b/docs/i18n/ar/README.md similarity index 100% rename from README.ar.md rename to docs/i18n/ar/README.md diff --git a/docs/i18n/ar/RELEASE_CHECKLIST.md b/docs/i18n/ar/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/ar/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/ar/TROUBLESHOOTING.md b/docs/i18n/ar/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/ar/TROUBLESHOOTING.md +++ b/docs/i18n/ar/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/ar/USER_GUIDE.md b/docs/i18n/ar/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/ar/USER_GUIDE.md +++ b/docs/i18n/ar/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/ar/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ar/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/ar/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/bg/A2A-SERVER.md b/docs/i18n/bg/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/bg/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/bg/API_REFERENCE.md b/docs/i18n/bg/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/bg/API_REFERENCE.md +++ b/docs/i18n/bg/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/bg/ARCHITECTURE.md b/docs/i18n/bg/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/bg/ARCHITECTURE.md +++ b/docs/i18n/bg/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/bg/AUTO-COMBO.md b/docs/i18n/bg/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/bg/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/bg/CODEBASE_DOCUMENTATION.md b/docs/i18n/bg/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/bg/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/bg/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/bg/FEATURES.md b/docs/i18n/bg/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/bg/FEATURES.md +++ b/docs/i18n/bg/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/bg/MCP-SERVER.md b/docs/i18n/bg/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/bg/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.bg.md b/docs/i18n/bg/README.md similarity index 100% rename from README.bg.md rename to docs/i18n/bg/README.md diff --git a/docs/i18n/bg/RELEASE_CHECKLIST.md b/docs/i18n/bg/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/bg/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/bg/TROUBLESHOOTING.md b/docs/i18n/bg/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/bg/TROUBLESHOOTING.md +++ b/docs/i18n/bg/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/bg/USER_GUIDE.md b/docs/i18n/bg/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/bg/USER_GUIDE.md +++ b/docs/i18n/bg/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/bg/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/bg/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/bg/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/da/A2A-SERVER.md b/docs/i18n/da/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/da/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/da/API_REFERENCE.md b/docs/i18n/da/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/da/API_REFERENCE.md +++ b/docs/i18n/da/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/da/ARCHITECTURE.md b/docs/i18n/da/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/da/ARCHITECTURE.md +++ b/docs/i18n/da/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/da/AUTO-COMBO.md b/docs/i18n/da/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/da/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/da/CODEBASE_DOCUMENTATION.md b/docs/i18n/da/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/da/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/da/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/da/FEATURES.md b/docs/i18n/da/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/da/FEATURES.md +++ b/docs/i18n/da/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/da/MCP-SERVER.md b/docs/i18n/da/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/da/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.da.md b/docs/i18n/da/README.md similarity index 100% rename from README.da.md rename to docs/i18n/da/README.md diff --git a/docs/i18n/da/RELEASE_CHECKLIST.md b/docs/i18n/da/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/da/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/da/TROUBLESHOOTING.md b/docs/i18n/da/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/da/TROUBLESHOOTING.md +++ b/docs/i18n/da/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/da/USER_GUIDE.md b/docs/i18n/da/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/da/USER_GUIDE.md +++ b/docs/i18n/da/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/da/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/da/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/da/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/de/A2A-SERVER.md b/docs/i18n/de/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/de/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/de/API_REFERENCE.md b/docs/i18n/de/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/de/API_REFERENCE.md +++ b/docs/i18n/de/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/de/ARCHITECTURE.md b/docs/i18n/de/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/de/ARCHITECTURE.md +++ b/docs/i18n/de/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/de/AUTO-COMBO.md b/docs/i18n/de/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/de/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/de/CODEBASE_DOCUMENTATION.md b/docs/i18n/de/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/de/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/de/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/de/FEATURES.md b/docs/i18n/de/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/de/FEATURES.md +++ b/docs/i18n/de/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/de/MCP-SERVER.md b/docs/i18n/de/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/de/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.de.md b/docs/i18n/de/README.md similarity index 100% rename from README.de.md rename to docs/i18n/de/README.md diff --git a/docs/i18n/de/RELEASE_CHECKLIST.md b/docs/i18n/de/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/de/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/de/TROUBLESHOOTING.md b/docs/i18n/de/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/de/TROUBLESHOOTING.md +++ b/docs/i18n/de/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/de/USER_GUIDE.md b/docs/i18n/de/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/de/USER_GUIDE.md +++ b/docs/i18n/de/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/de/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/de/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/de/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/es/A2A-SERVER.md b/docs/i18n/es/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/es/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/es/API_REFERENCE.md b/docs/i18n/es/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/es/API_REFERENCE.md +++ b/docs/i18n/es/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/es/ARCHITECTURE.md b/docs/i18n/es/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/es/ARCHITECTURE.md +++ b/docs/i18n/es/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/es/AUTO-COMBO.md b/docs/i18n/es/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/es/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/es/CODEBASE_DOCUMENTATION.md b/docs/i18n/es/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/es/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/es/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/es/FEATURES.md b/docs/i18n/es/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/es/FEATURES.md +++ b/docs/i18n/es/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/es/MCP-SERVER.md b/docs/i18n/es/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/es/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.es.md b/docs/i18n/es/README.md similarity index 100% rename from README.es.md rename to docs/i18n/es/README.md diff --git a/docs/i18n/es/RELEASE_CHECKLIST.md b/docs/i18n/es/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/es/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/es/TROUBLESHOOTING.md b/docs/i18n/es/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/es/TROUBLESHOOTING.md +++ b/docs/i18n/es/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/es/USER_GUIDE.md b/docs/i18n/es/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/es/USER_GUIDE.md +++ b/docs/i18n/es/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/es/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/es/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/es/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/fi/A2A-SERVER.md b/docs/i18n/fi/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/fi/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/fi/API_REFERENCE.md b/docs/i18n/fi/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/fi/API_REFERENCE.md +++ b/docs/i18n/fi/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/fi/ARCHITECTURE.md b/docs/i18n/fi/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/fi/ARCHITECTURE.md +++ b/docs/i18n/fi/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/fi/AUTO-COMBO.md b/docs/i18n/fi/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/fi/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/fi/CODEBASE_DOCUMENTATION.md b/docs/i18n/fi/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/fi/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/fi/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/fi/FEATURES.md b/docs/i18n/fi/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/fi/FEATURES.md +++ b/docs/i18n/fi/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/fi/MCP-SERVER.md b/docs/i18n/fi/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/fi/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.fi.md b/docs/i18n/fi/README.md similarity index 100% rename from README.fi.md rename to docs/i18n/fi/README.md diff --git a/docs/i18n/fi/RELEASE_CHECKLIST.md b/docs/i18n/fi/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/fi/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/fi/TROUBLESHOOTING.md b/docs/i18n/fi/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/fi/TROUBLESHOOTING.md +++ b/docs/i18n/fi/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/fi/USER_GUIDE.md b/docs/i18n/fi/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/fi/USER_GUIDE.md +++ b/docs/i18n/fi/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/fi/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/fi/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/fi/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/fr/A2A-SERVER.md b/docs/i18n/fr/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/fr/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/fr/API_REFERENCE.md b/docs/i18n/fr/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/fr/API_REFERENCE.md +++ b/docs/i18n/fr/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/fr/ARCHITECTURE.md b/docs/i18n/fr/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/fr/ARCHITECTURE.md +++ b/docs/i18n/fr/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/fr/AUTO-COMBO.md b/docs/i18n/fr/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/fr/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/fr/CODEBASE_DOCUMENTATION.md b/docs/i18n/fr/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/fr/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/fr/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/fr/FEATURES.md b/docs/i18n/fr/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/fr/FEATURES.md +++ b/docs/i18n/fr/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/fr/MCP-SERVER.md b/docs/i18n/fr/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/fr/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.fr.md b/docs/i18n/fr/README.md similarity index 100% rename from README.fr.md rename to docs/i18n/fr/README.md diff --git a/docs/i18n/fr/RELEASE_CHECKLIST.md b/docs/i18n/fr/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/fr/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/fr/TROUBLESHOOTING.md b/docs/i18n/fr/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/fr/TROUBLESHOOTING.md +++ b/docs/i18n/fr/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/fr/USER_GUIDE.md b/docs/i18n/fr/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/fr/USER_GUIDE.md +++ b/docs/i18n/fr/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/fr/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/fr/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/fr/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/he/A2A-SERVER.md b/docs/i18n/he/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/he/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/he/API_REFERENCE.md b/docs/i18n/he/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/he/API_REFERENCE.md +++ b/docs/i18n/he/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/he/ARCHITECTURE.md b/docs/i18n/he/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/he/ARCHITECTURE.md +++ b/docs/i18n/he/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/he/AUTO-COMBO.md b/docs/i18n/he/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/he/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/he/CODEBASE_DOCUMENTATION.md b/docs/i18n/he/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/he/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/he/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/he/FEATURES.md b/docs/i18n/he/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/he/FEATURES.md +++ b/docs/i18n/he/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/he/MCP-SERVER.md b/docs/i18n/he/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/he/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.he.md b/docs/i18n/he/README.md similarity index 100% rename from README.he.md rename to docs/i18n/he/README.md diff --git a/docs/i18n/he/RELEASE_CHECKLIST.md b/docs/i18n/he/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/he/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/he/TROUBLESHOOTING.md b/docs/i18n/he/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/he/TROUBLESHOOTING.md +++ b/docs/i18n/he/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/he/USER_GUIDE.md b/docs/i18n/he/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/he/USER_GUIDE.md +++ b/docs/i18n/he/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/he/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/he/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/he/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/hu/A2A-SERVER.md b/docs/i18n/hu/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/hu/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/hu/API_REFERENCE.md b/docs/i18n/hu/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/hu/API_REFERENCE.md +++ b/docs/i18n/hu/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/hu/ARCHITECTURE.md b/docs/i18n/hu/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/hu/ARCHITECTURE.md +++ b/docs/i18n/hu/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/hu/AUTO-COMBO.md b/docs/i18n/hu/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/hu/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/hu/CODEBASE_DOCUMENTATION.md b/docs/i18n/hu/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/hu/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/hu/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/hu/FEATURES.md b/docs/i18n/hu/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/hu/FEATURES.md +++ b/docs/i18n/hu/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/hu/MCP-SERVER.md b/docs/i18n/hu/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/hu/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.hu.md b/docs/i18n/hu/README.md similarity index 100% rename from README.hu.md rename to docs/i18n/hu/README.md diff --git a/docs/i18n/hu/RELEASE_CHECKLIST.md b/docs/i18n/hu/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/hu/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/hu/TROUBLESHOOTING.md b/docs/i18n/hu/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/hu/TROUBLESHOOTING.md +++ b/docs/i18n/hu/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/hu/USER_GUIDE.md b/docs/i18n/hu/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/hu/USER_GUIDE.md +++ b/docs/i18n/hu/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/hu/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/hu/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/hu/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/id/A2A-SERVER.md b/docs/i18n/id/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/id/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/id/API_REFERENCE.md b/docs/i18n/id/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/id/API_REFERENCE.md +++ b/docs/i18n/id/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/id/ARCHITECTURE.md b/docs/i18n/id/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/id/ARCHITECTURE.md +++ b/docs/i18n/id/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/id/AUTO-COMBO.md b/docs/i18n/id/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/id/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/id/CODEBASE_DOCUMENTATION.md b/docs/i18n/id/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/id/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/id/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/id/FEATURES.md b/docs/i18n/id/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/id/FEATURES.md +++ b/docs/i18n/id/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/id/MCP-SERVER.md b/docs/i18n/id/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/id/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.id.md b/docs/i18n/id/README.md similarity index 100% rename from README.id.md rename to docs/i18n/id/README.md diff --git a/docs/i18n/id/RELEASE_CHECKLIST.md b/docs/i18n/id/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/id/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/id/TROUBLESHOOTING.md b/docs/i18n/id/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/id/TROUBLESHOOTING.md +++ b/docs/i18n/id/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/id/USER_GUIDE.md b/docs/i18n/id/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/id/USER_GUIDE.md +++ b/docs/i18n/id/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/id/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/id/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/id/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/in/A2A-SERVER.md b/docs/i18n/in/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/in/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/in/API_REFERENCE.md b/docs/i18n/in/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/in/API_REFERENCE.md +++ b/docs/i18n/in/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/in/ARCHITECTURE.md b/docs/i18n/in/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/in/ARCHITECTURE.md +++ b/docs/i18n/in/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/in/AUTO-COMBO.md b/docs/i18n/in/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/in/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/in/CODEBASE_DOCUMENTATION.md b/docs/i18n/in/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/in/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/in/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/in/FEATURES.md b/docs/i18n/in/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/in/FEATURES.md +++ b/docs/i18n/in/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/in/MCP-SERVER.md b/docs/i18n/in/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/in/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.in.md b/docs/i18n/in/README.md similarity index 100% rename from README.in.md rename to docs/i18n/in/README.md diff --git a/docs/i18n/in/RELEASE_CHECKLIST.md b/docs/i18n/in/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/in/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/in/TROUBLESHOOTING.md b/docs/i18n/in/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/in/TROUBLESHOOTING.md +++ b/docs/i18n/in/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/in/USER_GUIDE.md b/docs/i18n/in/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/in/USER_GUIDE.md +++ b/docs/i18n/in/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/in/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/in/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/in/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/it/A2A-SERVER.md b/docs/i18n/it/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/it/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/it/API_REFERENCE.md b/docs/i18n/it/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/it/API_REFERENCE.md +++ b/docs/i18n/it/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/it/ARCHITECTURE.md b/docs/i18n/it/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/it/ARCHITECTURE.md +++ b/docs/i18n/it/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/it/AUTO-COMBO.md b/docs/i18n/it/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/it/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/it/CODEBASE_DOCUMENTATION.md b/docs/i18n/it/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/it/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/it/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/it/FEATURES.md b/docs/i18n/it/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/it/FEATURES.md +++ b/docs/i18n/it/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/it/MCP-SERVER.md b/docs/i18n/it/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/it/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.it.md b/docs/i18n/it/README.md similarity index 100% rename from README.it.md rename to docs/i18n/it/README.md diff --git a/docs/i18n/it/RELEASE_CHECKLIST.md b/docs/i18n/it/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/it/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/it/TROUBLESHOOTING.md b/docs/i18n/it/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/it/TROUBLESHOOTING.md +++ b/docs/i18n/it/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/it/USER_GUIDE.md b/docs/i18n/it/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/it/USER_GUIDE.md +++ b/docs/i18n/it/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/it/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/it/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/it/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/ja/A2A-SERVER.md b/docs/i18n/ja/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/ja/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/ja/API_REFERENCE.md b/docs/i18n/ja/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/ja/API_REFERENCE.md +++ b/docs/i18n/ja/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/ja/ARCHITECTURE.md b/docs/i18n/ja/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/ja/ARCHITECTURE.md +++ b/docs/i18n/ja/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/ja/AUTO-COMBO.md b/docs/i18n/ja/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/ja/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/ja/CODEBASE_DOCUMENTATION.md b/docs/i18n/ja/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/ja/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ja/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/ja/FEATURES.md b/docs/i18n/ja/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/ja/FEATURES.md +++ b/docs/i18n/ja/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/ja/MCP-SERVER.md b/docs/i18n/ja/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/ja/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.ja.md b/docs/i18n/ja/README.md similarity index 100% rename from README.ja.md rename to docs/i18n/ja/README.md diff --git a/docs/i18n/ja/RELEASE_CHECKLIST.md b/docs/i18n/ja/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/ja/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/ja/TROUBLESHOOTING.md b/docs/i18n/ja/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/ja/TROUBLESHOOTING.md +++ b/docs/i18n/ja/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/ja/USER_GUIDE.md b/docs/i18n/ja/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/ja/USER_GUIDE.md +++ b/docs/i18n/ja/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/ja/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ja/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/ja/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/ko/A2A-SERVER.md b/docs/i18n/ko/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/ko/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/ko/API_REFERENCE.md b/docs/i18n/ko/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/ko/API_REFERENCE.md +++ b/docs/i18n/ko/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/ko/ARCHITECTURE.md b/docs/i18n/ko/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/ko/ARCHITECTURE.md +++ b/docs/i18n/ko/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/ko/AUTO-COMBO.md b/docs/i18n/ko/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/ko/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/ko/CODEBASE_DOCUMENTATION.md b/docs/i18n/ko/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/ko/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ko/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/ko/FEATURES.md b/docs/i18n/ko/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/ko/FEATURES.md +++ b/docs/i18n/ko/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/ko/MCP-SERVER.md b/docs/i18n/ko/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/ko/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.ko.md b/docs/i18n/ko/README.md similarity index 100% rename from README.ko.md rename to docs/i18n/ko/README.md diff --git a/docs/i18n/ko/RELEASE_CHECKLIST.md b/docs/i18n/ko/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/ko/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/ko/TROUBLESHOOTING.md b/docs/i18n/ko/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/ko/TROUBLESHOOTING.md +++ b/docs/i18n/ko/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/ko/USER_GUIDE.md b/docs/i18n/ko/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/ko/USER_GUIDE.md +++ b/docs/i18n/ko/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/ko/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ko/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/ko/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/ms/A2A-SERVER.md b/docs/i18n/ms/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/ms/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/ms/API_REFERENCE.md b/docs/i18n/ms/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/ms/API_REFERENCE.md +++ b/docs/i18n/ms/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/ms/ARCHITECTURE.md b/docs/i18n/ms/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/ms/ARCHITECTURE.md +++ b/docs/i18n/ms/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/ms/AUTO-COMBO.md b/docs/i18n/ms/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/ms/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/ms/CODEBASE_DOCUMENTATION.md b/docs/i18n/ms/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/ms/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ms/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/ms/FEATURES.md b/docs/i18n/ms/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/ms/FEATURES.md +++ b/docs/i18n/ms/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/ms/MCP-SERVER.md b/docs/i18n/ms/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/ms/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.ms.md b/docs/i18n/ms/README.md similarity index 100% rename from README.ms.md rename to docs/i18n/ms/README.md diff --git a/docs/i18n/ms/RELEASE_CHECKLIST.md b/docs/i18n/ms/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/ms/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/ms/TROUBLESHOOTING.md b/docs/i18n/ms/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/ms/TROUBLESHOOTING.md +++ b/docs/i18n/ms/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/ms/USER_GUIDE.md b/docs/i18n/ms/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/ms/USER_GUIDE.md +++ b/docs/i18n/ms/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/ms/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ms/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/ms/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/nl/A2A-SERVER.md b/docs/i18n/nl/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/nl/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/nl/API_REFERENCE.md b/docs/i18n/nl/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/nl/API_REFERENCE.md +++ b/docs/i18n/nl/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/nl/ARCHITECTURE.md b/docs/i18n/nl/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/nl/ARCHITECTURE.md +++ b/docs/i18n/nl/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/nl/AUTO-COMBO.md b/docs/i18n/nl/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/nl/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/nl/CODEBASE_DOCUMENTATION.md b/docs/i18n/nl/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/nl/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/nl/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/nl/FEATURES.md b/docs/i18n/nl/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/nl/FEATURES.md +++ b/docs/i18n/nl/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/nl/MCP-SERVER.md b/docs/i18n/nl/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/nl/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.nl.md b/docs/i18n/nl/README.md similarity index 100% rename from README.nl.md rename to docs/i18n/nl/README.md diff --git a/docs/i18n/nl/RELEASE_CHECKLIST.md b/docs/i18n/nl/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/nl/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/nl/TROUBLESHOOTING.md b/docs/i18n/nl/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/nl/TROUBLESHOOTING.md +++ b/docs/i18n/nl/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/nl/USER_GUIDE.md b/docs/i18n/nl/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/nl/USER_GUIDE.md +++ b/docs/i18n/nl/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/nl/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/nl/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/nl/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/no/A2A-SERVER.md b/docs/i18n/no/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/no/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/no/API_REFERENCE.md b/docs/i18n/no/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/no/API_REFERENCE.md +++ b/docs/i18n/no/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/no/ARCHITECTURE.md b/docs/i18n/no/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/no/ARCHITECTURE.md +++ b/docs/i18n/no/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/no/AUTO-COMBO.md b/docs/i18n/no/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/no/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/no/CODEBASE_DOCUMENTATION.md b/docs/i18n/no/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/no/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/no/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/no/FEATURES.md b/docs/i18n/no/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/no/FEATURES.md +++ b/docs/i18n/no/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/no/MCP-SERVER.md b/docs/i18n/no/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/no/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.no.md b/docs/i18n/no/README.md similarity index 100% rename from README.no.md rename to docs/i18n/no/README.md diff --git a/docs/i18n/no/RELEASE_CHECKLIST.md b/docs/i18n/no/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/no/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/no/TROUBLESHOOTING.md b/docs/i18n/no/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/no/TROUBLESHOOTING.md +++ b/docs/i18n/no/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/no/USER_GUIDE.md b/docs/i18n/no/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/no/USER_GUIDE.md +++ b/docs/i18n/no/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/no/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/no/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/no/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/phi/A2A-SERVER.md b/docs/i18n/phi/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/phi/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/phi/API_REFERENCE.md b/docs/i18n/phi/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/phi/API_REFERENCE.md +++ b/docs/i18n/phi/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/phi/ARCHITECTURE.md b/docs/i18n/phi/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/phi/ARCHITECTURE.md +++ b/docs/i18n/phi/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/phi/AUTO-COMBO.md b/docs/i18n/phi/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/phi/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/phi/CODEBASE_DOCUMENTATION.md b/docs/i18n/phi/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/phi/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/phi/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/phi/FEATURES.md b/docs/i18n/phi/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/phi/FEATURES.md +++ b/docs/i18n/phi/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/phi/MCP-SERVER.md b/docs/i18n/phi/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/phi/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.phi.md b/docs/i18n/phi/README.md similarity index 100% rename from README.phi.md rename to docs/i18n/phi/README.md diff --git a/docs/i18n/phi/RELEASE_CHECKLIST.md b/docs/i18n/phi/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/phi/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/phi/TROUBLESHOOTING.md b/docs/i18n/phi/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/phi/TROUBLESHOOTING.md +++ b/docs/i18n/phi/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/phi/USER_GUIDE.md b/docs/i18n/phi/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/phi/USER_GUIDE.md +++ b/docs/i18n/phi/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/phi/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/phi/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/phi/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/pl/A2A-SERVER.md b/docs/i18n/pl/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/pl/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/pl/API_REFERENCE.md b/docs/i18n/pl/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/pl/API_REFERENCE.md +++ b/docs/i18n/pl/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/pl/ARCHITECTURE.md b/docs/i18n/pl/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/pl/ARCHITECTURE.md +++ b/docs/i18n/pl/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/pl/AUTO-COMBO.md b/docs/i18n/pl/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/pl/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/pl/CODEBASE_DOCUMENTATION.md b/docs/i18n/pl/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/pl/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/pl/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/pl/FEATURES.md b/docs/i18n/pl/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/pl/FEATURES.md +++ b/docs/i18n/pl/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/pl/MCP-SERVER.md b/docs/i18n/pl/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/pl/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.pl.md b/docs/i18n/pl/README.md similarity index 100% rename from README.pl.md rename to docs/i18n/pl/README.md diff --git a/docs/i18n/pl/RELEASE_CHECKLIST.md b/docs/i18n/pl/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/pl/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/pl/TROUBLESHOOTING.md b/docs/i18n/pl/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/pl/TROUBLESHOOTING.md +++ b/docs/i18n/pl/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/pl/USER_GUIDE.md b/docs/i18n/pl/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/pl/USER_GUIDE.md +++ b/docs/i18n/pl/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/pl/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/pl/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/pl/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/pt-BR/A2A-SERVER.md b/docs/i18n/pt-BR/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/pt-BR/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/pt-BR/API_REFERENCE.md b/docs/i18n/pt-BR/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/pt-BR/API_REFERENCE.md +++ b/docs/i18n/pt-BR/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/pt-BR/ARCHITECTURE.md b/docs/i18n/pt-BR/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/pt-BR/ARCHITECTURE.md +++ b/docs/i18n/pt-BR/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/pt-BR/AUTO-COMBO.md b/docs/i18n/pt-BR/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/pt-BR/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/pt-BR/CODEBASE_DOCUMENTATION.md b/docs/i18n/pt-BR/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/pt-BR/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/pt-BR/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/pt-BR/FEATURES.md b/docs/i18n/pt-BR/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/pt-BR/FEATURES.md +++ b/docs/i18n/pt-BR/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/pt-BR/MCP-SERVER.md b/docs/i18n/pt-BR/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/pt-BR/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.pt-BR.md b/docs/i18n/pt-BR/README.md similarity index 100% rename from README.pt-BR.md rename to docs/i18n/pt-BR/README.md diff --git a/docs/i18n/pt-BR/RELEASE_CHECKLIST.md b/docs/i18n/pt-BR/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/pt-BR/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/pt-BR/TROUBLESHOOTING.md b/docs/i18n/pt-BR/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/pt-BR/TROUBLESHOOTING.md +++ b/docs/i18n/pt-BR/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/pt-BR/USER_GUIDE.md b/docs/i18n/pt-BR/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/pt-BR/USER_GUIDE.md +++ b/docs/i18n/pt-BR/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/pt-BR/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/pt-BR/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/pt-BR/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/pt/A2A-SERVER.md b/docs/i18n/pt/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/pt/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/pt/API_REFERENCE.md b/docs/i18n/pt/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/pt/API_REFERENCE.md +++ b/docs/i18n/pt/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/pt/ARCHITECTURE.md b/docs/i18n/pt/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/pt/ARCHITECTURE.md +++ b/docs/i18n/pt/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/pt/AUTO-COMBO.md b/docs/i18n/pt/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/pt/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/pt/CODEBASE_DOCUMENTATION.md b/docs/i18n/pt/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/pt/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/pt/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/pt/FEATURES.md b/docs/i18n/pt/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/pt/FEATURES.md +++ b/docs/i18n/pt/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/pt/MCP-SERVER.md b/docs/i18n/pt/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/pt/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.pt.md b/docs/i18n/pt/README.md similarity index 100% rename from README.pt.md rename to docs/i18n/pt/README.md diff --git a/docs/i18n/pt/RELEASE_CHECKLIST.md b/docs/i18n/pt/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/pt/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/pt/TROUBLESHOOTING.md b/docs/i18n/pt/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/pt/TROUBLESHOOTING.md +++ b/docs/i18n/pt/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/pt/USER_GUIDE.md b/docs/i18n/pt/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/pt/USER_GUIDE.md +++ b/docs/i18n/pt/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/pt/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/pt/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/pt/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/ro/A2A-SERVER.md b/docs/i18n/ro/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/ro/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/ro/API_REFERENCE.md b/docs/i18n/ro/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/ro/API_REFERENCE.md +++ b/docs/i18n/ro/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/ro/ARCHITECTURE.md b/docs/i18n/ro/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/ro/ARCHITECTURE.md +++ b/docs/i18n/ro/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/ro/AUTO-COMBO.md b/docs/i18n/ro/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/ro/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/ro/CODEBASE_DOCUMENTATION.md b/docs/i18n/ro/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/ro/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ro/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/ro/FEATURES.md b/docs/i18n/ro/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/ro/FEATURES.md +++ b/docs/i18n/ro/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/ro/MCP-SERVER.md b/docs/i18n/ro/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/ro/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.ro.md b/docs/i18n/ro/README.md similarity index 100% rename from README.ro.md rename to docs/i18n/ro/README.md diff --git a/docs/i18n/ro/RELEASE_CHECKLIST.md b/docs/i18n/ro/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/ro/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/ro/TROUBLESHOOTING.md b/docs/i18n/ro/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/ro/TROUBLESHOOTING.md +++ b/docs/i18n/ro/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/ro/USER_GUIDE.md b/docs/i18n/ro/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/ro/USER_GUIDE.md +++ b/docs/i18n/ro/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/ro/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ro/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/ro/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/ru/A2A-SERVER.md b/docs/i18n/ru/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/ru/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/ru/API_REFERENCE.md b/docs/i18n/ru/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/ru/API_REFERENCE.md +++ b/docs/i18n/ru/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/ru/ARCHITECTURE.md b/docs/i18n/ru/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/ru/ARCHITECTURE.md +++ b/docs/i18n/ru/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/ru/AUTO-COMBO.md b/docs/i18n/ru/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/ru/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/ru/CODEBASE_DOCUMENTATION.md b/docs/i18n/ru/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/ru/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ru/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/ru/FEATURES.md b/docs/i18n/ru/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/ru/FEATURES.md +++ b/docs/i18n/ru/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/ru/MCP-SERVER.md b/docs/i18n/ru/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/ru/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.ru.md b/docs/i18n/ru/README.md similarity index 100% rename from README.ru.md rename to docs/i18n/ru/README.md diff --git a/docs/i18n/ru/RELEASE_CHECKLIST.md b/docs/i18n/ru/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/ru/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/ru/TROUBLESHOOTING.md b/docs/i18n/ru/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/ru/TROUBLESHOOTING.md +++ b/docs/i18n/ru/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/ru/USER_GUIDE.md b/docs/i18n/ru/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/ru/USER_GUIDE.md +++ b/docs/i18n/ru/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/ru/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ru/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/ru/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/sk/A2A-SERVER.md b/docs/i18n/sk/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/sk/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/sk/API_REFERENCE.md b/docs/i18n/sk/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/sk/API_REFERENCE.md +++ b/docs/i18n/sk/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/sk/ARCHITECTURE.md b/docs/i18n/sk/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/sk/ARCHITECTURE.md +++ b/docs/i18n/sk/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/sk/AUTO-COMBO.md b/docs/i18n/sk/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/sk/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/sk/CODEBASE_DOCUMENTATION.md b/docs/i18n/sk/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/sk/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/sk/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/sk/FEATURES.md b/docs/i18n/sk/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/sk/FEATURES.md +++ b/docs/i18n/sk/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/sk/MCP-SERVER.md b/docs/i18n/sk/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/sk/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.sk.md b/docs/i18n/sk/README.md similarity index 100% rename from README.sk.md rename to docs/i18n/sk/README.md diff --git a/docs/i18n/sk/RELEASE_CHECKLIST.md b/docs/i18n/sk/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/sk/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/sk/TROUBLESHOOTING.md b/docs/i18n/sk/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/sk/TROUBLESHOOTING.md +++ b/docs/i18n/sk/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/sk/USER_GUIDE.md b/docs/i18n/sk/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/sk/USER_GUIDE.md +++ b/docs/i18n/sk/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/sk/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/sk/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/sk/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/sv/A2A-SERVER.md b/docs/i18n/sv/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/sv/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/sv/API_REFERENCE.md b/docs/i18n/sv/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/sv/API_REFERENCE.md +++ b/docs/i18n/sv/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/sv/ARCHITECTURE.md b/docs/i18n/sv/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/sv/ARCHITECTURE.md +++ b/docs/i18n/sv/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/sv/AUTO-COMBO.md b/docs/i18n/sv/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/sv/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/sv/CODEBASE_DOCUMENTATION.md b/docs/i18n/sv/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/sv/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/sv/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/sv/FEATURES.md b/docs/i18n/sv/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/sv/FEATURES.md +++ b/docs/i18n/sv/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/sv/MCP-SERVER.md b/docs/i18n/sv/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/sv/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.sv.md b/docs/i18n/sv/README.md similarity index 100% rename from README.sv.md rename to docs/i18n/sv/README.md diff --git a/docs/i18n/sv/RELEASE_CHECKLIST.md b/docs/i18n/sv/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/sv/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/sv/TROUBLESHOOTING.md b/docs/i18n/sv/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/sv/TROUBLESHOOTING.md +++ b/docs/i18n/sv/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/sv/USER_GUIDE.md b/docs/i18n/sv/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/sv/USER_GUIDE.md +++ b/docs/i18n/sv/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/sv/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/sv/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/sv/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/th/A2A-SERVER.md b/docs/i18n/th/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/th/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/th/API_REFERENCE.md b/docs/i18n/th/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/th/API_REFERENCE.md +++ b/docs/i18n/th/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/th/ARCHITECTURE.md b/docs/i18n/th/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/th/ARCHITECTURE.md +++ b/docs/i18n/th/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/th/AUTO-COMBO.md b/docs/i18n/th/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/th/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/th/CODEBASE_DOCUMENTATION.md b/docs/i18n/th/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/th/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/th/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/th/FEATURES.md b/docs/i18n/th/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/th/FEATURES.md +++ b/docs/i18n/th/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/th/MCP-SERVER.md b/docs/i18n/th/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/th/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.th.md b/docs/i18n/th/README.md similarity index 100% rename from README.th.md rename to docs/i18n/th/README.md diff --git a/docs/i18n/th/RELEASE_CHECKLIST.md b/docs/i18n/th/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/th/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/th/TROUBLESHOOTING.md b/docs/i18n/th/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/th/TROUBLESHOOTING.md +++ b/docs/i18n/th/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/th/USER_GUIDE.md b/docs/i18n/th/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/th/USER_GUIDE.md +++ b/docs/i18n/th/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/th/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/th/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/th/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/uk-UA/A2A-SERVER.md b/docs/i18n/uk-UA/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/uk-UA/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/uk-UA/API_REFERENCE.md b/docs/i18n/uk-UA/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/uk-UA/API_REFERENCE.md +++ b/docs/i18n/uk-UA/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/uk-UA/ARCHITECTURE.md b/docs/i18n/uk-UA/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/uk-UA/ARCHITECTURE.md +++ b/docs/i18n/uk-UA/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/uk-UA/AUTO-COMBO.md b/docs/i18n/uk-UA/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/uk-UA/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/uk-UA/CODEBASE_DOCUMENTATION.md b/docs/i18n/uk-UA/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/uk-UA/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/uk-UA/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/uk-UA/FEATURES.md b/docs/i18n/uk-UA/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/uk-UA/FEATURES.md +++ b/docs/i18n/uk-UA/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/uk-UA/MCP-SERVER.md b/docs/i18n/uk-UA/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/uk-UA/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.uk-UA.md b/docs/i18n/uk-UA/README.md similarity index 100% rename from README.uk-UA.md rename to docs/i18n/uk-UA/README.md diff --git a/docs/i18n/uk-UA/RELEASE_CHECKLIST.md b/docs/i18n/uk-UA/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/uk-UA/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/uk-UA/TROUBLESHOOTING.md b/docs/i18n/uk-UA/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/uk-UA/TROUBLESHOOTING.md +++ b/docs/i18n/uk-UA/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/uk-UA/USER_GUIDE.md b/docs/i18n/uk-UA/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/uk-UA/USER_GUIDE.md +++ b/docs/i18n/uk-UA/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/uk-UA/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/uk-UA/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/uk-UA/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/vi/A2A-SERVER.md b/docs/i18n/vi/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/vi/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/vi/API_REFERENCE.md b/docs/i18n/vi/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/vi/API_REFERENCE.md +++ b/docs/i18n/vi/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/vi/ARCHITECTURE.md b/docs/i18n/vi/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/vi/ARCHITECTURE.md +++ b/docs/i18n/vi/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/vi/AUTO-COMBO.md b/docs/i18n/vi/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/vi/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/vi/CODEBASE_DOCUMENTATION.md b/docs/i18n/vi/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/vi/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/vi/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/vi/FEATURES.md b/docs/i18n/vi/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/vi/FEATURES.md +++ b/docs/i18n/vi/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/vi/MCP-SERVER.md b/docs/i18n/vi/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/vi/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.vi.md b/docs/i18n/vi/README.md similarity index 100% rename from README.vi.md rename to docs/i18n/vi/README.md diff --git a/docs/i18n/vi/RELEASE_CHECKLIST.md b/docs/i18n/vi/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/vi/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/vi/TROUBLESHOOTING.md b/docs/i18n/vi/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/vi/TROUBLESHOOTING.md +++ b/docs/i18n/vi/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/vi/USER_GUIDE.md b/docs/i18n/vi/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/vi/USER_GUIDE.md +++ b/docs/i18n/vi/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/vi/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/vi/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/vi/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/docs/i18n/zh-CN/A2A-SERVER.md b/docs/i18n/zh-CN/A2A-SERVER.md new file mode 100644 index 0000000000..01531ff482 --- /dev/null +++ b/docs/i18n/zh-CN/A2A-SERVER.md @@ -0,0 +1,200 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md) + +--- + +# OmniRoute A2A Server Documentation + +> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent + +## Agent Discovery + +```bash +curl http://localhost:20128/.well-known/agent.json +``` + +Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements. + +--- + +## Authentication + +All `/a2a` requests require an API key via the `Authorization` header: + +``` +Authorization: Bearer YOUR_OMNIROUTE_API_KEY +``` + +If no API key is configured on the server, authentication is bypassed. + +--- + +## JSON-RPC 2.0 Methods + +### `message/send` — Synchronous Execution + +Sends a message to a skill and waits for the complete response. + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Write a hello world in Python"}], + "metadata": {"model": "auto", "combo": "fast-coding"} + } + }' +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "result": { + "task": { "id": "uuid", "state": "completed" }, + "artifacts": [{ "type": "text", "content": "..." }], + "metadata": { + "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", + "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, + "resilience_trace": [ + { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } + ], + "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } + } + } +} +``` + +### `message/stream` — SSE Streaming + +Same as `message/send` but returns Server-Sent Events for real-time streaming. + +```bash +curl -N -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{ + "jsonrpc": "2.0", + "id": "1", + "method": "message/stream", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Explain quantum computing"}] + } + }' +``` + +**SSE Events:** + +``` +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} + +: heartbeat 2026-03-03T17:00:00Z + +data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} +``` + +### `tasks/get` — Query Task Status + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}' +``` + +### `tasks/cancel` — Cancel a Task + +```bash +curl -X POST http://localhost:20128/a2a \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}' +``` + +--- + +## Available Skills + +| Skill | Description | +| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. | +| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. | + +--- + +## Task Lifecycle + +``` +submitted → working → completed + → failed + → cancelled +``` + +- Tasks expire after 5 minutes (configurable) +- Terminal states: `completed`, `failed`, `cancelled` +- Event log tracks every state transition + +--- + +## Error Codes + +| Code | Meaning | +| :----- | :----------------------------- | +| -32700 | Parse error (invalid JSON) | +| -32600 | Invalid request / Unauthorized | +| -32601 | Method or skill not found | +| -32602 | Invalid params | +| -32603 | Internal error | + +--- + +## Integration Examples + +### Python (requests) + +```python +import requests + +resp = requests.post("http://localhost:20128/a2a", json={ + "jsonrpc": "2.0", "id": "1", + "method": "message/send", + "params": { + "skill": "smart-routing", + "messages": [{"role": "user", "content": "Hello"}] + } +}, headers={"Authorization": "Bearer YOUR_KEY"}) + +result = resp.json()["result"] +print(result["artifacts"][0]["content"]) +print(result["metadata"]["routing_explanation"]) +``` + +### TypeScript (fetch) + +```typescript +const resp = await fetch("http://localhost:20128/a2a", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer YOUR_KEY", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: "1", + method: "message/send", + params: { + skill: "smart-routing", + messages: [{ role: "user", content: "Hello" }], + }, + }), +}); +const { result } = await resp.json(); +console.log(result.metadata.routing_explanation); +``` diff --git a/docs/i18n/zh-CN/API_REFERENCE.md b/docs/i18n/zh-CN/API_REFERENCE.md index b795722c11..b878605221 100644 --- a/docs/i18n/zh-CN/API_REFERENCE.md +++ b/docs/i18n/zh-CN/API_REFERENCE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md) + +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) diff --git a/docs/i18n/zh-CN/ARCHITECTURE.md b/docs/i18n/zh-CN/ARCHITECTURE.md index 258d62df53..4381dcf4c5 100644 --- a/docs/i18n/zh-CN/ARCHITECTURE.md +++ b/docs/i18n/zh-CN/ARCHITECTURE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md) + +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) diff --git a/docs/i18n/zh-CN/AUTO-COMBO.md b/docs/i18n/zh-CN/AUTO-COMBO.md new file mode 100644 index 0000000000..2166e41dff --- /dev/null +++ b/docs/i18n/zh-CN/AUTO-COMBO.md @@ -0,0 +1,67 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md) + +--- + +# OmniRoute Auto-Combo Engine + +> Self-managing model chains with adaptive scoring + +## How It Works + +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**: + +| Factor | Weight | Description | +| :--------- | :----- | :---------------------------------------------- | +| Quota | 0.20 | Remaining capacity [0..1] | +| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 | +| CostInv | 0.20 | Inverse cost (cheaper = higher score) | +| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) | +| TaskFit | 0.10 | Model × task type fitness score | +| Stability | 0.10 | Low variance in latency/errors | + +## Mode Packs + +| Pack | Focus | Key Weight | +| :---------------------- | :----------- | :--------------- | +| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 | +| 💰 **Cost Saver** | Economy | costInv: 0.40 | +| 🎯 **Quality First** | Best model | taskFit: 0.40 | +| 📡 **Offline Friendly** | Availability | quota: 0.40 | + +## Self-Healing + +- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min) +- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests +- **Incident mode**: >50% OPEN → disable exploration, maximize stability +- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout + +## Bandit Exploration + +5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode. + +## API + +```bash +# Create auto-combo +curl -X POST http://localhost:20128/api/combos/auto \ + -H "Content-Type: application/json" \ + -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' + +# List auto-combos +curl http://localhost:20128/api/combos/auto +``` + +## Task Fitness + +30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score). + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------ | +| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization | +| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup | +| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap | +| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode | +| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles | +| `src/app/api/combos/auto/route.ts` | REST API | diff --git a/docs/i18n/zh-CN/CODEBASE_DOCUMENTATION.md b/docs/i18n/zh-CN/CODEBASE_DOCUMENTATION.md index 303880c198..856df322e0 100644 --- a/docs/i18n/zh-CN/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/zh-CN/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md) + +--- + # omniroute — Codebase Documentation 🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md) diff --git a/docs/i18n/zh-CN/FEATURES.md b/docs/i18n/zh-CN/FEATURES.md index e047e02a57..9b265d3c7a 100644 --- a/docs/i18n/zh-CN/FEATURES.md +++ b/docs/i18n/zh-CN/FEATURES.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/FEATURES.md) · 🇪🇸 [es](../es/FEATURES.md) · 🇫🇷 [fr](../fr/FEATURES.md) · 🇩🇪 [de](../de/FEATURES.md) · 🇮🇹 [it](../it/FEATURES.md) · 🇷🇺 [ru](../ru/FEATURES.md) · 🇨🇳 [zh-CN](../zh-CN/FEATURES.md) · 🇯🇵 [ja](../ja/FEATURES.md) · 🇰🇷 [ko](../ko/FEATURES.md) · 🇸🇦 [ar](../ar/FEATURES.md) · 🇮🇳 [in](../in/FEATURES.md) · 🇹🇭 [th](../th/FEATURES.md) · 🇻🇳 [vi](../vi/FEATURES.md) · 🇮🇩 [id](../id/FEATURES.md) · 🇲🇾 [ms](../ms/FEATURES.md) · 🇳🇱 [nl](../nl/FEATURES.md) · 🇵🇱 [pl](../pl/FEATURES.md) · 🇸🇪 [sv](../sv/FEATURES.md) · 🇳🇴 [no](../no/FEATURES.md) · 🇩🇰 [da](../da/FEATURES.md) · 🇫🇮 [fi](../fi/FEATURES.md) · 🇵🇹 [pt](../pt/FEATURES.md) · 🇷🇴 [ro](../ro/FEATURES.md) · 🇭🇺 [hu](../hu/FEATURES.md) · 🇧🇬 [bg](../bg/FEATURES.md) · 🇸🇰 [sk](../sk/FEATURES.md) · 🇺🇦 [uk-UA](../uk-UA/FEATURES.md) · 🇮🇱 [he](../he/FEATURES.md) · 🇵🇭 [phi](../phi/FEATURES.md) + +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵 [日本語](i18n/ja/FEATURES.md) | 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) diff --git a/docs/i18n/zh-CN/MCP-SERVER.md b/docs/i18n/zh-CN/MCP-SERVER.md new file mode 100644 index 0000000000..829acd30b1 --- /dev/null +++ b/docs/i18n/zh-CN/MCP-SERVER.md @@ -0,0 +1,87 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md) + +--- + +# OmniRoute MCP Server Documentation + +> Model Context Protocol server with 16 intelligent tools + +## Installation + +OmniRoute MCP is built-in. Start it with: + +```bash +omniroute --mcp +``` + +Or via the open-sse transport: + +```bash +# HTTP streamable transport (port 20130) +omniroute --dev # MCP auto-starts on /mcp endpoint +``` + +## IDE Configuration + +See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup. + +--- + +## Essential Tools (8) + +| Tool | Description | +| :------------------------------ | :--------------------------------------- | +| `omniroute_get_health` | Gateway health, circuit breakers, uptime | +| `omniroute_list_combos` | All configured combos with models | +| `omniroute_get_combo_metrics` | Performance metrics for a specific combo | +| `omniroute_switch_combo` | Switch active combo by ID/name | +| `omniroute_check_quota` | Quota status per provider or all | +| `omniroute_route_request` | Send a chat completion through OmniRoute | +| `omniroute_cost_report` | Cost analytics for a time period | +| `omniroute_list_models_catalog` | Full model catalog with capabilities | + +## Advanced Tools (8) + +| Tool | Description | +| :--------------------------------- | :---------------------------------------------- | +| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree | +| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions | +| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset | +| `omniroute_test_combo` | Live-test all models in a combo | +| `omniroute_get_provider_metrics` | Detailed metrics for one provider | +| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives | +| `omniroute_explain_route` | Explain a past routing decision | +| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors | + +## Authentication + +MCP tools are authenticated via API key scopes. Each tool requires specific scopes: + +| Scope | Tools | +| :------------- | :----------------------------------------------- | +| `read:health` | get_health, get_provider_metrics | +| `read:combos` | list_combos, get_combo_metrics | +| `write:combos` | switch_combo | +| `read:quota` | check_quota | +| `write:route` | route_request, simulate_route, test_combo | +| `read:usage` | cost_report, get_session_snapshot, explain_route | +| `write:config` | set_budget_guard, set_resilience_profile | +| `read:models` | list_models_catalog, best_combo_for_task | + +## Audit Logging + +Every tool call is logged to `mcp_tool_audit` with: + +- Tool name, arguments, result +- Duration (ms), success/failure +- API key hash, timestamp + +## Files + +| File | Purpose | +| :------------------------------------------- | :------------------------------------------ | +| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations | +| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport | +| `open-sse/mcp-server/auth.ts` | API key + scope validation | +| `open-sse/mcp-server/audit.ts` | Tool call audit logging | +| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers | diff --git a/README.zh-CN.md b/docs/i18n/zh-CN/README.md similarity index 100% rename from README.zh-CN.md rename to docs/i18n/zh-CN/README.md diff --git a/docs/i18n/zh-CN/RELEASE_CHECKLIST.md b/docs/i18n/zh-CN/RELEASE_CHECKLIST.md new file mode 100644 index 0000000000..903e812c3f --- /dev/null +++ b/docs/i18n/zh-CN/RELEASE_CHECKLIST.md @@ -0,0 +1,37 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md) + +--- + +# Release Checklist + +Use this checklist before tagging or publishing a new OmniRoute release. + +## Version and Changelog + +1. Bump `package.json` version (`x.y.z`) in the release branch. +2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section: + - `## [x.y.z] — YYYY-MM-DD` +3. Keep `## [Unreleased]` as the first changelog section for upcoming work. +4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version. + +## API Docs + +1. Update `docs/openapi.yaml`: + - `info.version` must equal `package.json` version. +2. Validate endpoint examples if API contracts changed. + +## Runtime Docs + +1. Review `docs/ARCHITECTURE.md` for storage/runtime drift. +2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift. +3. Update localized docs if source docs changed significantly. + +## Automated Check + +Run the sync guard locally before opening PR: + +```bash +npm run check:docs-sync +``` + +CI also runs this check in `.github/workflows/ci.yml` (lint job). diff --git a/docs/i18n/zh-CN/TROUBLESHOOTING.md b/docs/i18n/zh-CN/TROUBLESHOOTING.md index 120092d63c..4584113406 100644 --- a/docs/i18n/zh-CN/TROUBLESHOOTING.md +++ b/docs/i18n/zh-CN/TROUBLESHOOTING.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md) + +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) diff --git a/docs/i18n/zh-CN/USER_GUIDE.md b/docs/i18n/zh-CN/USER_GUIDE.md index 5a043224df..66c67ad892 100644 --- a/docs/i18n/zh-CN/USER_GUIDE.md +++ b/docs/i18n/zh-CN/USER_GUIDE.md @@ -1,3 +1,7 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md) + +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) diff --git a/docs/i18n/zh-CN/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/zh-CN/VM_DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000000..f0734d9a9e --- /dev/null +++ b/docs/i18n/zh-CN/VM_DEPLOYMENT_GUIDE.md @@ -0,0 +1,403 @@ +🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../es/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../fr/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../de/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../it/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../ru/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../ja/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../ko/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../ar/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../in/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../th/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../vi/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../id/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../ms/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../nl/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../pl/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../sv/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../no/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../da/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../fi/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../pt/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../ro/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../hu/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../bg/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../sk/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../he/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../phi/VM_DEPLOYMENT_GUIDE.md) + +--- + +# OmniRoute — Guia de Deploy em VM com Cloudflare + +Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare. + +--- + +## Pré-Requisitos + +| Item | Mínimo | Recomendado | +| ----------- | ------------------------ | ---------------- | +| **CPU** | 1 vCPU | 2 vCPU | +| **RAM** | 1 GB | 2 GB | +| **Disco** | 10 GB SSD | 25 GB SSD | +| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS | +| **Domínio** | Registrado no Cloudflare | — | +| **Docker** | Docker Engine 24+ | Docker 27+ | + +**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail. + +--- + +## 1. Configurar a VM + +### 1.1 Criar a instância + +No seu provider de VPS preferido: + +- Escolha Ubuntu 24.04 LTS +- Selecione o plano mínimo (1 vCPU / 1 GB RAM) +- Defina uma senha forte para root ou configure SSH key +- Anote o **IP público** (ex: `203.0.113.10`) + +### 1.2 Conectar via SSH + +```bash +ssh root@203.0.113.10 +``` + +### 1.3 Atualizar o sistema + +```bash +apt update && apt upgrade -y +``` + +### 1.4 Instalar Docker + +```bash +# Instalar dependências +apt install -y ca-certificates curl gnupg + +# Adicionar repositório oficial do Docker +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt update +apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +``` + +### 1.5 Instalar nginx + +```bash +apt install -y nginx +``` + +### 1.6 Configurar Firewall (UFW) + +```bash +ufw default deny incoming +ufw default allow outgoing +ufw allow 22/tcp # SSH +ufw allow 80/tcp # HTTP (redirect) +ufw allow 443/tcp # HTTPS +ufw enable +``` + +> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada). + +--- + +## 2. Instalar o OmniRoute + +### 2.1 Criar diretório de configuração + +```bash +mkdir -p /opt/omniroute +``` + +### 2.2 Criar arquivo de variáveis de ambiente + +```bash +cat > /opt/omniroute/.env << 'EOF' +# === Segurança === +JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS +INITIAL_PASSWORD=SuaSenhaSegura123! +API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA +STORAGE_ENCRYPTION_KEY_VERSION=v1 +MACHINE_ID_SALT=ALTERE-PARA-SALT-UNICO + +# === App === +PORT=20128 +NODE_ENV=production +HOSTNAME=0.0.0.0 +DATA_DIR=/app/data +STORAGE_DRIVER=sqlite +ENABLE_REQUEST_LOGS=true +AUTH_COOKIE_SECURE=false +REQUIRE_API_KEY=false + +# === Domain (altere para seu domínio) === +BASE_URL=https://llms.seudominio.com +NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com + +# === Cloud Sync (opcional) === +# CLOUD_URL=https://cloud.omniroute.online +# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online +EOF +``` + +> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave. + +### 2.3 Iniciar o container + +```bash +docker pull diegosouzapw/omniroute:latest + +docker run -d \ + --name omniroute \ + --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### 2.4 Verificar se está rodando + +```bash +docker ps | grep omniroute +docker logs omniroute --tail 20 +``` + +Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`. + +--- + +## 3. Configurar nginx (Reverse Proxy) + +### 3.1 Gerar certificado SSL (Cloudflare Origin) + +No painel da Cloudflare: + +1. Vá em **SSL/TLS → Origin Server** +2. Clique **Create Certificate** +3. Deixe os padrões (15 anos, \*.seudominio.com) +4. Copie o **Origin Certificate** e a **Private Key** + +```bash +mkdir -p /etc/nginx/ssl + +# Colar o certificado +nano /etc/nginx/ssl/origin.crt + +# Colar a chave privada +nano /etc/nginx/ssl/origin.key + +chmod 600 /etc/nginx/ssl/origin.key +``` + +### 3.2 Configuração do nginx + +```bash +cat > /etc/nginx/sites-available/omniroute << 'NGINX' +# Default server — bloqueia acesso direto por IP +server { + listen 80 default_server; + listen [::]:80 default_server; + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + server_name _; + return 444; +} + +# OmniRoute — HTTPS +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name llms.seudominio.com; # Altere para seu domínio + + ssl_certificate /etc/nginx/ssl/origin.crt; + ssl_certificate_key /etc/nginx/ssl/origin.key; + ssl_protocols TLSv1.2 TLSv1.3; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:20128; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # SSE (Server-Sent Events) — streaming AI responses + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } +} + +# HTTP → HTTPS redirect +server { + listen 80; + listen [::]:80; + server_name llms.seudominio.com; + return 301 https://$server_name$request_uri; +} +NGINX +``` + +### 3.3 Ativar e testar + +```bash +# Remover config padrão +rm -f /etc/nginx/sites-enabled/default + +# Ativar OmniRoute +ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute + +# Testar e recarregar +nginx -t && systemctl reload nginx +``` + +--- + +## 4. Configurar Cloudflare DNS + +### 4.1 Adicionar registro DNS + +No painel da Cloudflare → DNS: + +| Type | Name | Content | Proxy | +| ---- | ------ | ------------------------- | ---------- | +| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied | + +### 4.2 Configurar SSL + +Em **SSL/TLS → Overview**: + +- Modo: **Full (Strict)** + +Em **SSL/TLS → Edge Certificates**: + +- Always Use HTTPS: ✅ On +- Minimum TLS Version: TLS 1.2 +- Automatic HTTPS Rewrites: ✅ On + +### 4.3 Testar + +```bash +curl -sI https://llms.seudominio.com/health +# Deve retornar HTTP/2 200 +``` + +--- + +## 5. Operações e Manutenção + +### Atualizar para nova versão + +```bash +docker pull diegosouzapw/omniroute:latest +docker stop omniroute && docker rm omniroute +docker run -d --name omniroute --restart unless-stopped \ + --env-file /opt/omniroute/.env \ + -p 20128:20128 \ + -v omniroute-data:/app/data \ + diegosouzapw/omniroute:latest +``` + +### Ver logs + +```bash +docker logs -f omniroute # Stream em tempo real +docker logs omniroute --tail 50 # Últimas 50 linhas +``` + +### Backup manual do banco + +```bash +# Copiar dados do volume para o host +docker cp omniroute:/app/data ./backup-$(date +%F) + +# Ou comprimir todo o volume +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data +``` + +### Restaurar de backup + +```bash +docker stop omniroute +docker run --rm -v omniroute-data:/data -v $(pwd):/backup \ + alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /" +docker start omniroute +``` + +--- + +## 6. Segurança Avançada + +### Restringir nginx para Cloudflare IPs + +```bash +cat > /etc/nginx/cloudflare-ips.conf << 'CF' +# Cloudflare IPv4 ranges — atualizar periodicamente +# https://www.cloudflare.com/ips-v4/ +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; +set_real_ip_from 131.0.72.0/22; +real_ip_header CF-Connecting-IP; +CF +``` + +Adicionar no `nginx.conf` dentro do bloco `http {}`: + +```nginx +include /etc/nginx/cloudflare-ips.conf; +``` + +### Install fail2ban + +```bash +apt install -y fail2ban +systemctl enable fail2ban +systemctl start fail2ban + +# Verificar status +fail2ban-client status sshd +``` + +### Bloquear acesso direto na porta do Docker + +```bash +# Impedir acesso externo direto à porta 20128 +iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP +iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT + +# Persistir as regras +apt install -y iptables-persistent +netfilter-persistent save +``` + +--- + +## 7. Deploy do Cloud Worker (Opcional) + +Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente): + +```bash +# No repositório local +cd omnirouteCloud +npm install +npx wrangler login +npx wrangler deploy +``` + +Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md). + +--- + +## Resumo de Portas + +| Porta | Serviço | Acesso | +| ----- | ----------- | ----------------------------- | +| 22 | SSH | Público (com fail2ban) | +| 80 | nginx HTTP | Redirect → HTTPS | +| 443 | nginx HTTPS | Via Cloudflare Proxy | +| 20128 | OmniRoute | Somente localhost (via nginx) | diff --git a/open-sse/services/usage.ts b/open-sse/services/usage.ts index 9993d8174f..e432e812f5 100644 --- a/open-sse/services/usage.ts +++ b/open-sse/services/usage.ts @@ -477,13 +477,13 @@ async function getClaudeUsage(accessToken) { if (oauthResponse.ok) { const data = await oauthResponse.json(); - const quotas: Record = {}; + const quotas: Record = {}; // utilization = percentage REMAINING (e.g., 90 means 90% remaining, 10% used) - const hasUtilization = (window: any) => + const hasUtilization = (window: JsonRecord) => window && typeof window === "object" && safePercentage(window.utilization) !== undefined; - const createQuotaObject = (window: any) => { + const createQuotaObject = (window: JsonRecord) => { const remaining = safePercentage(window.utilization) as number; const used = 100 - remaining; return { @@ -506,9 +506,10 @@ async function getClaudeUsage(accessToken) { // Parse model-specific weekly windows (e.g., seven_day_sonnet, seven_day_opus) for (const [key, value] of Object.entries(data)) { - if (key.startsWith("seven_day_") && key !== "seven_day" && hasUtilization(value)) { + const valueRecord = toRecord(value); + if (key.startsWith("seven_day_") && key !== "seven_day" && hasUtilization(valueRecord)) { const modelName = key.replace("seven_day_", ""); - quotas[`weekly ${modelName} (7d)`] = createQuotaObject(value); + quotas[`weekly ${modelName} (7d)`] = createQuotaObject(valueRecord); } } @@ -525,7 +526,7 @@ async function getClaudeUsage(accessToken) { ); return await getClaudeUsageLegacy(accessToken); } catch (error) { - return { message: `Claude connected. Unable to fetch usage: ${(error as any).message}` }; + return { message: `Claude connected. Unable to fetch usage: ${(error as Error).message}` }; } } @@ -577,7 +578,7 @@ async function getClaudeUsageLegacy(accessToken) { return { message: "Claude connected. Usage API requires admin permissions." }; } catch (error) { - return { message: `Claude connected. Unable to fetch usage: ${(error as any).message}` }; + return { message: `Claude connected. Unable to fetch usage: ${(error as Error).message}` }; } } diff --git a/package-lock.json b/package-lock.json index 582f831666..9f92e4d57b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "omniroute", - "version": "2.0.20", + "version": "2.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "omniroute", - "version": "2.0.20", + "version": "2.1.1", "hasInstallScript": true, "license": "MIT", "workspaces": [ diff --git a/package.json b/package.json index 78ba38ce52..27076ab97e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "omniroute", - "version": "2.1.0", + "version": "2.1.1", "description": "Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.", "type": "module", "bin": {