Skip to content

Commit 88ad4cc

Browse files
committed
feat: add MCP server, A2A protocol, auto-combo engine & VS Code extension
Introduce full AI orchestration ecosystem: - MCP Server with 16 tools, scoped auth, and audit logging - A2A v0.3 server with JSON-RPC 2.0, SSE streaming, and task manager - Auto-Combo engine with 6-factor scoring and self-healing - VS Code extension with smart dispatch and budget tracking - Harden CI pipeline: add static checks, remove continue-on-error - Add translator schema validation tests - Update .gitignore and CHANGELOG for release checklist
1 parent ab77452 commit 88ad4cc

26 files changed

+1311
-51
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ jobs:
2222
cache: npm
2323
- run: npm ci
2424
- run: npm run lint
25+
- run: npm run check:cycles
26+
- run: npm run check:route-validation:t06
27+
- run: npm run check:any-budget:t11
28+
- run: npm run check:docs-sync
29+
- run: npm run typecheck:core
30+
- run: npm run typecheck:noimplicit:core
2531

2632
security:
2733
name: Security Audit
@@ -127,7 +133,6 @@ jobs:
127133
cache: npm
128134
- run: npm ci
129135
- run: npm run test:integration
130-
continue-on-error: true
131136

132137
test-security:
133138
name: Security Tests
@@ -144,4 +149,3 @@ jobs:
144149
cache: npm
145150
- run: npm ci
146151
- run: npm run test:security
147-
continue-on-error: true

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ docs/*
6363
!docs/TASK_NEBIUS_BACKEND_ENABLEMENT.md
6464
!docs/frontend-backend-provider-gap-report.md
6565
!docs/openapi.yaml
66+
!docs/RELEASE_CHECKLIST.md
6667
!docs/PLANO-IMPLANTACAO.md
6768
!docs/TASKS.md
6869
!docs/FASE-*.md
@@ -106,7 +107,7 @@ app.__qa_backup/
106107
# Production standalone build (created by scripts/prepublish.mjs)
107108
# Conflicts with Next.js App Router detection in dev (root app/ shadows src/app/)
108109
# npm publish still includes it via package.json "files" field
109-
app/
110+
/app/
110111

111112
# Electron (subproject dependency lock and build artifacts)
112113
electron/package-lock.json

CHANGELOG.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,78 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
---
99

10+
## [Unreleased]
11+
12+
> ### ✨ Major Feature Release — MCP Server, A2A Protocol, Auto-Combo Engine & VS Code Extension
13+
>
14+
> Full AI orchestration ecosystem: 16 MCP tools, A2A v0.3 server, self-healing Auto-Combo engine, and a VS Code extension with smart dispatch, budget tracking, and human checkpoints.
15+
16+
### 🆕 MCP Server (16 Tools)
17+
18+
- **8 Essential Tools**`get_health`, `list_combos`, `get_combo_metrics`, `switch_combo`, `check_quota`, `route_request`, `cost_report`, `list_models_catalog`
19+
- **8 Advanced Tools**`simulate_route`, `set_budget_guard`, `set_resilience_profile`, `test_combo`, `get_provider_metrics`, `best_combo_for_task`, `explain_route`, `get_session_snapshot`
20+
- **Scoped Authorization** — 8 permission scopes (read:health, write:combo, etc.)
21+
- **Audit Logging** — Every tool call logged with duration, arguments, and result
22+
- **IDE Configs** — MCP configuration templates for Antigravity, Cursor, Copilot, Claude Desktop
23+
24+
### 🤖 A2A Server (Agent-to-Agent v0.3)
25+
26+
- **JSON-RPC 2.0** — Full router with `message/send`, `message/stream`, `tasks/get`, `tasks/cancel`
27+
- **Agent Card** — Dynamic `/.well-known/agent.json` with 2 skills
28+
- **Skills**`smart-routing` (routing explanation, cost envelope, resilience trace, policy verdict) and `quota-management` (natural language quota queries)
29+
- **SSE Streaming** — Real-time task streaming with 15s heartbeat
30+
- **Task Manager** — State machine (submitted→working→completed/failed/canceled), TTL, cleanup
31+
- **Routing Logger** — Decision audit trail with 7-day retention
32+
33+
### ⚡ Auto-Combo Engine
34+
35+
- **6-Factor Scoring** — Quota, health, costInv, latencyInv, taskFit, stability (normalized 0-1)
36+
- **Task Fitness Table** — 30+ models × 6 task types with wildcard boosts
37+
- **4 Mode Packs** — Ship Fast, Cost Saver, Quality First, Offline Friendly
38+
- **Self-Healing** — Progressive cooldown exclusion, probe-based re-admission, incident mode (>50% OPEN)
39+
- **Bandit Exploration** — 5% exploratory routing for discovering better providers
40+
- **Adaptation Persistence** — EMA scoring with disk persistence every 10 decisions
41+
- **REST API**`POST/GET /api/combos/auto` for CRUD operations
42+
43+
### 🧩 VS Code Extension — Advanced Features
44+
45+
- **MCP Client** — 16 tool wrappers with REST API fallback
46+
- **A2A Client** — Agent discovery, message send/stream, task management
47+
- **Smart Dispatch** — Task type detection, combo recommendation, risk scoring
48+
- **Preflight Dialog** — Risk-based display (auto-skip low, info medium, modal high)
49+
- **Budget Guard** — Session cost tracking with status bar indicator and threshold actions
50+
- **Mode Pack Selector** — Quick-pick UI for switching optimization profiles
51+
- **Health Monitor** — Circuit breaker state change notifications
52+
- **Human Checkpoint** — Multi-factor confidence evaluation with handoff dialog
53+
54+
### 📊 Dashboard Pages
55+
56+
- **MCP Dashboard** — Tool listing, usage stats, audit log with 30s auto-refresh
57+
- **A2A Dashboard** — Agent Card display, skill listing, task history with routing metadata
58+
- **Auto-Combo Dashboard** — Provider score bars, factor breakdown, mode pack selector, incident indicator, exclusion list
59+
60+
### 🔗 Integrations
61+
62+
- **OpenClaw** — Dynamic `provider.order` endpoint at `/api/cli-tools/openclaw/auto-order`
63+
64+
### 🧪 Tests
65+
66+
- **E2E Test Suite** — 6 scenarios (MCP, A2A, Auto-Combo, OpenClaw, Stress 100+50 parallel, Security)
67+
- **Unit Tests** — Essential tools, advanced tools, extension services, Auto-Combo engine, extension advanced features
68+
69+
### 📁 New Files (35+)
70+
71+
| Directory | Files |
72+
| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- |
73+
| `open-sse/mcp-server/` | `server.ts`, `transport.ts`, `auth.ts`, `audit.ts`, `tools/advancedTools.ts` |
74+
| `src/lib/a2a/` | `taskManager.ts`, `streaming.ts`, `routingLogger.ts`, `skills/smartRouting.ts`, `skills/quotaManagement.ts` |
75+
| `open-sse/services/autoCombo/` | `scoring.ts`, `taskFitness.ts`, `engine.ts`, `selfHealing.ts`, `modePacks.ts`, `persistence.ts`, `index.ts` |
76+
| `vscode-extension/src/services/` | `mcpClient.ts`, `a2aClient.ts`, `policyEngine.ts`, `preflightDialog.ts`, `budgetGuard.ts`, `healthMonitor.ts`, `modePackSelector.ts`, `humanCheckpoint.ts` |
77+
| `src/app/(dashboard)/` | `dashboard/mcp/page.tsx`, `dashboard/a2a/page.tsx`, `dashboard/auto-combo/page.tsx` |
78+
| `docs/` | `mcp-server.md`, `a2a-server.md`, `auto-combo.md`, `vscode-extension.md`, `integrations/ide-configs.md` |
79+
80+
---
81+
1082
## [1.8.1] — 2026-03-03
1183

1284
### 🐛 Bug Fixes

docs/ARCHITECTURE.md

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
🌐 **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)
44

5-
_Last updated: 2026-02-18_
5+
_Last updated: 2026-03-04_
66

77
## Executive Summary
88

@@ -81,8 +81,8 @@ flowchart LR
8181
API[V1 Compatibility API\n/v1/*]
8282
DASH[Dashboard + Management API\n/api/*]
8383
CORE[SSE + Translation Core\nopen-sse + src/sse]
84-
DB[(db.json)]
85-
UDB[(usage.json + log.txt)]
84+
DB[(storage.sqlite)]
85+
UDB[(usage tables + log artifacts)]
8686
end
8787
8888
subgraph Upstreams[Upstream Providers]
@@ -144,7 +144,7 @@ Management domains:
144144
- Providers/connections: `src/app/api/providers*`
145145
- Provider nodes: `src/app/api/provider-nodes*`
146146
- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
147-
- Model catalog: `src/app/api/models/catalog` (GET)
147+
- Model catalog: `src/app/api/models/route.ts` (GET)
148148
- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
149149
- OAuth: `src/app/api/oauth/*`
150150
- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
@@ -225,18 +225,19 @@ OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
225225

226226
## 3) Persistence Layer
227227

228-
Primary state DB:
228+
Primary state DB (SQLite):
229229

230-
- `src/lib/localDb.ts`
231-
- file: `${DATA_DIR}/db.json` (or `$XDG_CONFIG_HOME/omniroute/db.json` when set, else `~/.omniroute/db.json`)
232-
- entities: providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
230+
- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
231+
- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
232+
- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
233+
- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
233234

234-
Usage DB:
235+
Usage persistence:
235236

236-
- `src/lib/usageDb.ts`
237-
- files: `${DATA_DIR}/usage.json`, `${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`
238-
- follows same base directory policy as `localDb` (`DATA_DIR`, then `XDG_CONFIG_HOME/omniroute` when set)
239-
- decomposed into focused sub-modules: `migrations.ts`, `usageHistory.ts`, `costCalculator.ts`, `usageStats.ts`, `callLogs.ts`
237+
- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
238+
- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
239+
- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `<repo>/logs/...`)
240+
- legacy JSON files are migrated to SQLite by startup migrations when present
240241

241242
Domain State DB (SQLite):
242243

@@ -505,9 +506,9 @@ erDiagram
505506

506507
Physical storage files:
507508

508-
- main state: `${DATA_DIR}/db.json` (or `$XDG_CONFIG_HOME/omniroute/db.json` when set, else `~/.omniroute/db.json`)
509-
- usage stats: `${DATA_DIR}/usage.json`
510-
- request log lines: `${DATA_DIR}/log.txt`
509+
- primary runtime DB: `${DATA_DIR}/storage.sqlite`
510+
- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
511+
- structured call payload archives: `${DATA_DIR}/call_logs/`
511512
- optional translator/request debug sessions: `<repo>/logs/...`
512513

513514
## Deployment Topology
@@ -522,8 +523,8 @@ flowchart LR
522523
subgraph ContainerOrProcess[OmniRoute Runtime]
523524
Next[Next.js Server\nPORT=20128]
524525
Core[SSE Core + Executors]
525-
MainDB[(db.json)]
526-
UsageDB[(usage.json/log.txt)]
526+
MainDB[(storage.sqlite)]
527+
UsageDB[(usage tables + log artifacts)]
527528
end
528529
529530
subgraph External[External Services]
@@ -550,7 +551,7 @@ flowchart LR
550551
- `src/app/api/providers*`: provider CRUD, validation, testing
551552
- `src/app/api/provider-nodes*`: custom compatible node management
552553
- `src/app/api/provider-models`: custom model management (CRUD)
553-
- `src/app/api/models/catalog`: full model catalog API (all types grouped by provider)
554+
- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
554555
- `src/app/api/oauth/*`: OAuth/device-code flows
555556
- `src/app/api/keys*`: local API key lifecycle
556557
- `src/app/api/models/alias`: alias management
@@ -582,8 +583,9 @@ flowchart LR
582583

583584
### Persistence
584585

585-
- `src/lib/localDb.ts`: persistent config/state
586-
- `src/lib/usageDb.ts`: usage history and rolling request logs
586+
- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
587+
- `src/lib/localDb.ts`: compatibility re-export for DB modules
588+
- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
587589

588590
## Provider Executor Coverage (Strategy Pattern)
589591

@@ -724,23 +726,23 @@ Files are written to `<repo>/logs/<session>/` for each request session.
724726

725727
## 5) Data Integrity
726728

727-
- DB shape migration/repair for missing keys
728-
- corrupt JSON reset safeguards for localDb and usageDb
729+
- SQLite schema migrations and auto-upgrade hooks at startup
730+
- legacy JSON → SQLite migration compatibility path
729731

730732
## Observability and Operational Signals
731733

732734
Runtime visibility sources:
733735

734736
- console logs from `src/sse/utils/logger.ts`
735-
- per-request usage aggregates in `usage.json`
736-
- textual request status log in `log.txt`
737+
- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
738+
- textual request status log in `log.txt` (optional/compat)
737739
- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
738740
- dashboard usage endpoints (`/api/usage/*`) for UI consumption
739741

740742
## Security-Sensitive Boundaries
741743

742744
- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
743-
- Initial password fallback (`INITIAL_PASSWORD`, default `123456`) must be overridden in real deployments
745+
- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
744746
- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
745747
- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
746748
- Cloud sync endpoints rely on API key auth + machine id semantics
@@ -762,13 +764,13 @@ Environment variables actively used by code:
762764

763765
## Known Architectural Notes
764766

765-
1. `usageDb` and `localDb` now share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
766-
2. `/api/v1/route.ts` returns a static model list and is not the main models source used by `/v1/models`.
767+
1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
768+
2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
767769
3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
768770
4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
769771
5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
770772
6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
771-
7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:plan3`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
773+
7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
772774
8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
773775

774776
## Operational Verification Checklist

docs/RELEASE_CHECKLIST.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Release Checklist
2+
3+
Use this checklist before tagging or publishing a new OmniRoute release.
4+
5+
## Version and Changelog
6+
7+
1. Bump `package.json` version (`x.y.z`) in the release branch.
8+
2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
9+
- `## [x.y.z] — YYYY-MM-DD`
10+
3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
11+
4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
12+
13+
## API Docs
14+
15+
1. Update `docs/openapi.yaml`:
16+
- `info.version` must equal `package.json` version.
17+
2. Validate endpoint examples if API contracts changed.
18+
19+
## Runtime Docs
20+
21+
1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
22+
2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
23+
3. Update localized docs if source docs changed significantly.
24+
25+
## Automated Check
26+
27+
Run the sync guard locally before opening PR:
28+
29+
```bash
30+
npm run check:docs-sync
31+
```
32+
33+
CI also runs this check in `.github/workflows/ci.yml` (lint job).

docs/TROUBLESHOOTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Common problems and solutions for OmniRoute.
1010

1111
| Problem | Solution |
1212
| ----------------------------- | ------------------------------------------------------------------ |
13-
| First login not working | Check `INITIAL_PASSWORD` in `.env` (default: `123456`) |
13+
| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
1414
| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
1515
| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
1616
| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
@@ -120,8 +120,8 @@ curl http://localhost:20128/api/monitoring/health
120120

121121
### Runtime Storage
122122

123-
- Main state: `${DATA_DIR}/db.json` (providers, combos, aliases, keys, settings)
124-
- Usage: `${DATA_DIR}/usage.json`, `${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`
123+
- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
124+
- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
125125
- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
126126

127127
---

docs/openapi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
openapi: 3.1.0
22
info:
33
title: OmniRoute API
4-
version: 0.5.0
4+
version: 1.8.1
55
description: |
66
OmniRoute is a local-first AI API proxy router. It provides an OpenAI-compatible
77
endpoint that routes requests to multiple AI providers with load balancing,

0 commit comments

Comments
 (0)