mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 23:02:10 +03:00
226 lines
8.7 KiB
Markdown
226 lines
8.7 KiB
Markdown
# CLAUDE.md — AI Agent Session Bootstrap
|
|
|
|
> Quick-start context for AI coding agents. For deep architecture details, see `AGENTS.md`.
|
|
> For contribution workflow, see `CONTRIBUTING.md`.
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
npm install # Install deps (auto-generates .env from .env.example)
|
|
npm run dev # Dev server at http://localhost:20128
|
|
npm run build # Production build (Next.js 16 standalone)
|
|
npm run lint # ESLint (0 errors expected; warnings are pre-existing)
|
|
npm run typecheck:core # TypeScript check (should be clean)
|
|
npm run test:coverage # Unit tests + coverage gate (60% min)
|
|
npm run check # lint + test combined
|
|
```
|
|
|
|
### Running a Single Test
|
|
|
|
```bash
|
|
# Node.js native test runner (most tests)
|
|
node --import tsx/esm --test tests/unit/your-file.test.mjs
|
|
|
|
# Vitest (MCP server, autoCombo, cache)
|
|
npm run test:vitest
|
|
```
|
|
|
|
---
|
|
|
|
## Project at a Glance
|
|
|
|
**OmniRoute** — unified AI proxy/router. One endpoint, 100+ LLM providers, auto-fallback.
|
|
|
|
| Layer | Location | Purpose |
|
|
| --------------- | ------------------------ | ------------------------------------------ |
|
|
| API Routes | `src/app/api/v1/` | Next.js App Router — entry points |
|
|
| Handlers | `open-sse/handlers/` | Request processing (chat, embeddings, etc) |
|
|
| Executors | `open-sse/executors/` | Provider-specific HTTP dispatch |
|
|
| Translators | `open-sse/translator/` | Format conversion (OpenAI↔Claude↔Gemini) |
|
|
| Services | `open-sse/services/` | Combo routing, rate limits, caching, etc |
|
|
| Database | `src/lib/db/` | SQLite domain modules (22 files) |
|
|
| Domain/Policy | `src/domain/` | Policy engine, cost rules, fallback logic |
|
|
| MCP Server | `open-sse/mcp-server/` | 25 tools, 3 transports, 10 scopes |
|
|
| A2A Server | `src/lib/a2a/` | JSON-RPC 2.0 agent protocol |
|
|
| Skills | `src/lib/skills/` | Extensible skill framework |
|
|
| Memory | `src/lib/memory/` | Persistent conversational memory |
|
|
| UI Components | `src/shared/components/` | React components (Tailwind CSS v4) |
|
|
| Provider Consts | `src/shared/constants/` | Provider registry (Zod-validated) |
|
|
| Validation | `src/shared/validation/` | Zod v4 schemas |
|
|
| Tests | `tests/` | Unit, integration, e2e, security, load |
|
|
|
|
### Monorepo Layout
|
|
|
|
```
|
|
OmniRoute/ # Root package
|
|
├── src/ # Next.js 16 app (TypeScript)
|
|
├── open-sse/ # @omniroute/open-sse workspace (streaming engine)
|
|
├── electron/ # Desktop app (Electron)
|
|
├── tests/ # All test suites
|
|
├── docs/ # Documentation
|
|
└── bin/ # CLI entry point
|
|
```
|
|
|
|
---
|
|
|
|
## Request Pipeline (Abbreviated)
|
|
|
|
```
|
|
Client → /v1/chat/completions (Next.js route)
|
|
→ CORS → Zod validation → auth? → policy check → prompt injection guard
|
|
→ handleChatCore() [open-sse/handlers/chatCore.ts]
|
|
→ cache check → rate limit → combo routing?
|
|
→ resolveComboTargets() → handleSingleModel() per target
|
|
→ translateRequest() → getExecutor() → executor.execute()
|
|
→ fetch() upstream → retry w/ backoff
|
|
→ response translation → SSE stream or JSON
|
|
```
|
|
|
|
---
|
|
|
|
## Key Conventions
|
|
|
|
### Code Style
|
|
|
|
- **2 spaces**, semicolons, double quotes, 100 char width, es5 trailing commas
|
|
- **Imports**: external → internal (`@/`, `@omniroute/open-sse`) → relative
|
|
- **Naming**: files=camelCase/kebab, components=PascalCase, constants=UPPER_SNAKE
|
|
|
|
### Database Access
|
|
|
|
- **Always** go through `src/lib/db/` domain modules
|
|
- **Never** write raw SQL in routes or handlers
|
|
- **Never** add logic to `src/lib/localDb.ts` (re-export layer only)
|
|
- **Never** barrel-import from `localDb.ts` — import specific `db/` modules
|
|
- DB singleton: `getDbInstance()` from `src/lib/db/core.ts` (WAL journaling)
|
|
- Migrations: `src/lib/db/migrations/` — 21 versioned SQL files
|
|
|
|
### Error Handling
|
|
|
|
- try/catch with specific error types, log with pino context
|
|
- Never swallow errors in SSE streams — use abort signals
|
|
- Return proper HTTP status codes (4xx/5xx)
|
|
|
|
### Security
|
|
|
|
- **Never** commit secrets/credentials
|
|
- **Never** use `eval()`, `new Function()`, or implied eval
|
|
- Validate all inputs with Zod schemas
|
|
- Encrypt credentials at rest (AES-256-GCM)
|
|
|
|
---
|
|
|
|
## Common Modification Scenarios
|
|
|
|
### Adding a New Provider
|
|
|
|
1. Register in `src/shared/constants/providers.ts` (Zod-validated at load)
|
|
2. Add executor in `open-sse/executors/` if custom logic needed
|
|
3. Add translator in `open-sse/translator/` if non-OpenAI format
|
|
4. Add OAuth config in `src/lib/oauth/constants/oauth.ts` if OAuth-based
|
|
5. Register models in `open-sse/config/providerRegistry.ts`
|
|
6. Write tests in `tests/unit/` (registration, translation, error handling)
|
|
|
|
### Adding a New API Route
|
|
|
|
1. Create directory under `src/app/api/v1/your-route/`
|
|
2. Create `route.ts` with `GET`/`POST` handlers
|
|
3. Follow pattern: CORS → Zod body validation → optional auth → handler delegation
|
|
4. Handler goes in `open-sse/handlers/` (import from there, not inline)
|
|
5. Add tests
|
|
|
|
### Adding a New DB Module
|
|
|
|
1. Create `src/lib/db/yourModule.ts`
|
|
2. Import `getDbInstance` from `./core.ts`
|
|
3. Export CRUD functions for your domain table(s)
|
|
4. Add migration in `src/lib/db/migrations/` if new tables needed
|
|
5. Re-export from `src/lib/localDb.ts` (add to the re-export list only)
|
|
6. Write tests
|
|
|
|
### Adding a New MCP Tool
|
|
|
|
1. Add tool definition in `open-sse/mcp-server/tools/`
|
|
2. Define Zod input schema + async handler
|
|
3. Register in tool set (wired by `createMcpServer()`)
|
|
4. Assign to appropriate scope(s)
|
|
5. Write tests (tool invocation logged to `mcp_audit` table)
|
|
|
|
### Adding a New A2A Skill
|
|
|
|
1. Create skill in `src/lib/a2a/skills/`
|
|
2. Skill receives task context (messages, metadata) → returns structured result
|
|
3. Register in the DB-backed skill registry
|
|
4. Write tests
|
|
|
|
---
|
|
|
|
## Testing Cheat Sheet
|
|
|
|
| What | Command |
|
|
| ----------------------- | ------------------------------------------------------- |
|
|
| All tests | `npm run test:all` |
|
|
| Unit tests | `npm run test:unit` |
|
|
| Single file | `node --import tsx/esm --test tests/unit/file.test.mjs` |
|
|
| Vitest (MCP, autoCombo) | `npm run test:vitest` |
|
|
| E2E (Playwright) | `npm run test:e2e` |
|
|
| Protocol E2E (MCP+A2A) | `npm run test:protocols:e2e` |
|
|
| Ecosystem | `npm run test:ecosystem` |
|
|
| Coverage gate | `npm run test:coverage` (60% min all metrics) |
|
|
| Coverage report | `npm run coverage:report` |
|
|
|
|
**PR rule**: If you change production code in `src/`, `open-sse/`, `electron/`, or `bin/`,
|
|
you must include or update tests in the same PR.
|
|
|
|
---
|
|
|
|
## Git Workflow
|
|
|
|
```bash
|
|
# Never commit directly to main
|
|
git checkout -b feat/your-feature
|
|
# ... make changes ...
|
|
git commit -m "feat: describe your change"
|
|
git push -u origin feat/your-feature
|
|
```
|
|
|
|
**Branch prefixes**: `feat/`, `fix/`, `refactor/`, `docs/`, `test/`, `chore/`
|
|
|
|
**Commit format** ([Conventional Commits](https://www.conventionalcommits.org/)):
|
|
|
|
```
|
|
feat: add circuit breaker for provider calls
|
|
fix: resolve JWT secret validation edge case
|
|
docs: update AGENTS.md with pipeline internals
|
|
test: add MCP tool unit tests
|
|
refactor(db): consolidate rate limit tables
|
|
```
|
|
|
|
**Scopes**: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`,
|
|
`memory`, `skills`.
|
|
|
|
---
|
|
|
|
## Environment
|
|
|
|
- **Runtime**: Node.js ≥18 <24, ES Modules
|
|
- **TypeScript**: 5.9, target ES2022, module esnext, resolution bundler
|
|
- **Path aliases**: `@/*` → `src/`, `@omniroute/open-sse` → `open-sse/`
|
|
- **Default port**: 20128 (API + dashboard on same port)
|
|
- **Data directory**: `DATA_DIR` env var, defaults to `~/.omniroute/`
|
|
- **Key env vars**: `PORT`, `JWT_SECRET`, `INITIAL_PASSWORD`, `REQUIRE_API_KEY`, `APP_LOG_LEVEL`
|
|
|
|
---
|
|
|
|
## Hard Rules (Never Violate)
|
|
|
|
1. Never commit secrets or credentials
|
|
2. Never add logic to `localDb.ts`
|
|
3. Never use `eval()` / `new Function()` / implied eval
|
|
4. Never commit directly to `main`
|
|
5. Never write raw SQL in routes — use `src/lib/db/` modules
|
|
6. Never silently swallow errors in SSE streams
|
|
7. Always validate inputs with Zod schemas
|
|
8. Always include tests when changing production code
|
|
9. Coverage must stay ≥60% (statements, lines, functions, branches)
|