1,104 mirrors rewritten over five passes of run-translation on the 22-source core set: the 14 sources edited since their translation, the 322 mirrors that were still English copies, and the frontmatter the old extractor leaked into the newer locales' bodies. The pipeline now caches per-`## `-section hashes and retranslates only changed sections, never reuses a section that is still English, rebuilds English-copy / leaked mirrors even when the source is unchanged, merges the state on save (parallel runs), and the drift gate (scoped to the core set) is blocking. Final audit: 0 stale, 0 English copies, 0 leaked frontmatter across 1,430 core mirrors. ⚠️ base-red inherited: #12732
24 KiB
Contributing to OmniRoute (Deutsch)
🌐 Languages: 🇺🇸 English · 🇪🇹 am · 🇸🇦 ar · 🇦🇿 az · 🇧🇬 bg · 🇧🇩 bn · 🇨🇿 cs · 🇩🇰 da · 🇬🇷 el · 🇪🇸 es · 🇪🇪 et · 🇮🇷 fa · 🇫🇮 fi · 🇫🇷 fr · 🇮🇪 ga · 🇮🇳 gu · 🇳🇬 ha · 🇮🇱 he · 🇮🇳 hi · 🇭🇷 hr · 🇭🇺 hu · 🇦🇲 hy · 🇮🇩 id · 🇳🇬 ig · 🇮🇹 it · 🇯🇵 ja · 🇬🇪 ka · 🇰🇭 km · 🇮🇳 kn · 🇰🇷 ko · 🇱🇹 lt · 🇱🇻 lv · 🇮🇳 ml · 🇮🇳 mr · 🇲🇾 ms · 🇲🇹 mt · 🇲🇲 my · 🇳🇵 ne · 🇳🇱 nl · 🇳🇴 no · 🇮🇳 or · 🇮🇳 pa · 🇵🇭 phi · 🇵🇱 pl · 🇵🇹 pt · 🇧🇷 pt-BR · 🇷🇴 ro · 🇷🇺 ru · 🇱🇰 si · 🇸🇰 sk · 🇸🇮 sl · 🇷🇸 sr · 🇸🇪 sv · 🇰🇪 sw · 🇮🇳 ta · 🇮🇳 te · 🇹🇭 th · 🇹🇷 tr · 🇺🇦 uk-UA · 🇵🇰 ur · 🇺🇿 uz · 🇻🇳 vi · 🇳🇬 yo · 🇨🇳 zh-CN · 🇹🇼 zh-TW
Thank you for your interest in contributing! This guide covers everything you need to get started.
Entwicklungsumgebung
Voraussetzungen
- Node.js
>=22.22.3 <23oder>=24.0.0 <27(empfohlen: 24 LTS) - npm 10+
Benutzer von npm v11+ (Node 24+): Überprüfen Sie nach
npm install, ob die nativen Module installiert wurden:node -e "require('better-sqlite3')". Falls der Befehl mitMODULE_NOT_FOUNDfehlschlägt, führen Sienpm approve-scripts better-sqlite3 && npm installaus. Siehe Fehlerbehebung.
- Git
Klonen und installieren
git clone https://github.com/diegosouzapw/OmniRoute.git
cd OmniRoute
npm install
Umgebungsvariablen
# Erstellen Sie Ihre .env aus der Vorlage
cp .env.example .env
# Erforderliche Geheimnisse generieren
echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
Wichtige Variablen für die Entwicklung:
| Variable | Entwicklungsstandardwert | Beschreibung |
|---|---|---|
PORT |
20128 |
Server-Port |
NEXT_PUBLIC_BASE_URL |
http://localhost:20128 |
Basis-URL für das Frontend |
JWT_SECRET |
(oben generieren) | Geheimnis für JWT-Signaturen |
INITIAL_PASSWORD |
CHANGEME |
Passwort für die erste Anmeldung |
APP_LOG_LEVEL |
info |
Ausführlichkeitsstufe der Protokollierung |
Dashboard-Einstellungen
Das Dashboard bietet UI-Umschalter für Funktionen, die auch über Umgebungsvariablen konfiguriert werden können:
| Ort der Einstellung | Umschalter | Beschreibung |
|---|---|---|
| Einstellungen → Erweitert | Debug-Modus | Debug-Protokolle für Anfragen aktivieren (UI) |
| Einstellungen → Allgemein | Sichtbarkeit der Seitenleiste | Bereiche der Seitenleiste ein-/ausblenden |
Diese Einstellungen werden in der Datenbank gespeichert, bleiben über Neustarts hinweg erhalten und überschreiben nach ihrer Festlegung die Standardwerte der Umgebungsvariablen.
Lokal ausführen
# Entwicklungsmodus (automatisches Neuladen)
npm run dev
# Produktions-Build
npm run build # next build → .build/next/, dann assembleStandalone → dist/
npm run start
# Schnelle reine Backend-/API-Kompilierung für Änderungen von Mitwirkenden
npm run build:contributor
# Release-Build (vollständiger Neuaufbau + HEAD-Sentinel — für die Bereitstellung erforderlich)
npm run build:release # rm -rf .build dist && Build + schreibt dist/BUILD_SHA
# Übliche Port-Konfiguration
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
Der Contributor-Build führt ausschließlich eine Kompilierungsvalidierung durch: Er erstellt weder die eigenständige Distribution noch optionale native Paketierungsartefakte. Verwenden Sie den regulären Produktions-Build, wenn Sie das auslieferbare Bundle validieren müssen.
Struktur der Build-Ausgabe
| Verzeichnis | Inhalt | Versioniert |
|---|---|---|
src/ |
Anwendungsquellcode (TypeScript / TSX) | Ja |
.build/ |
Zwischenergebnisse — Ausgabe von next build (von Git ignoriert, distDir = .build/next) |
Nein |
dist/ |
Auslieferbares Bundle — von assembleStandalone zusammengestellt (von Git ignoriert) |
Nein |
Die Build-Pipeline besteht aus einem einzigen Durchlauf:
npm run build
└─ next build → .build/next/standalone (Next.js-Ausgabe)
└─ assembleStandalone() (kopiert Standalone-Dateien + statische Dateien + öffentliche Dateien + native Assets)
└─ Ausgabe: dist/ (server.js, .next/static/, public/, node_modules/)
npm run build:release bereinigt zunächst zusätzlich beide Verzeichnisse und schreibt
dist/BUILD_SHA (= git rev-parse --short HEAD) als Integritäts-Sentinel für die Bereitstellung.
npm run build:contributor verwendet das reine Backend-Build-Profil. Während des Builds werden
Dashboard-UI-Dateien vorübergehend durch Stubs ersetzt, API-Routen-Handler beibehalten und die Originaldateien
nach dem Build wiederhergestellt. Verwenden Sie npm run build für Änderungen an der Dashboard-UI oder für eine
vollständige Release-Validierung; das Contributor-Profil ist kein Ersatz für den Release-Build.
Hinweis zur VPS-Bereitstellung: Das Remote-Image-Verzeichnis
/usr/lib/node_modules/omniroute/app/bleibt unverändert. Die Bereitstellungs-Skills synchronisieren den Inhalt vondist/per rsync dorthin. Nur der Pfad der Build-Ausgabe im Repository wurde geändert (app/→dist/).
Standard-URLs:
- Dashboard:
http://localhost:20128/dashboard - API:
http://localhost:20128/v1
Git-Workflow
⚠️ NIEMALS direkt in
maincommitten. Verwende immer Feature-Branches.PR-Basis: Verwende den aktiven
release/vX.Y.Z-Branch als Ziel (nichtmain). Siehedocs/ops/BRANCHING_MODEL.mdfür das Modell „ein Branch pro Release“ mit Tagging bei der Veröffentlichung.
# Vom aktuellen Stand des aktiven Release-Branches abzweigen (Beispiel: release/v3.8.49)
git fetch origin
git checkout -b feat/your-feature-name origin/release/v3.8.49
# ... Änderungen vornehmen ...
git commit -m "feat: describe your change"
git push -u origin feat/your-feature-name
# Einen Pull Request mit base = release/v3.8.49 öffnen
Branch-Benennung
| Präfix | Zweck |
|---|---|
feat/ |
Neue Funktionen |
fix/ |
Fehlerbehebungen |
refactor/ |
Umstrukturierung des Codes |
docs/ |
Änderungen an der Dokumentation |
test/ |
Ergänzungen/Korrekturen von Tests |
chore/ |
Tooling, CI, Abhängigkeiten |
Commit-Nachrichten
Befolge Conventional Commits:
feat: add circuit breaker for provider calls
fix: resolve JWT secret validation edge case
docs: update SECURITY.md with PII protection
test: add observability unit tests
refactor(db): consolidate rate limit tables
Scopes (v3.8): db, sse, oauth, dashboard, api, cli, docker, ci, mcp, a2a, memory, skills, cloud-agent, guardrails, compression, auto-combo, resilience, providers, executors, translator, domain, authz.
Tests ausführen
# Alle Tests (Unit + Vitest + Ökosystem + E2E)
npm run test:all
# Einzelne Testdatei (nativer Test-Runner von Node.js — die meisten Tests verwenden diesen)
node --import tsx/esm --test tests/unit/your-file.test.ts
# Nur die von deiner Änderung betroffenen Unit-Tests (derselbe TIA-Selektor wie beim CI-Gate, #8084)
npm run test:scoped # Änderungen im letzten Commit (oder im Arbeitsverzeichnis)
npm run test:scoped:staged # nur bereitgestellte Änderungen — eignet sich gut für einen Pre-Commit-Lauf
npm run test:scoped:full # zuerst die Import-Graph-Zuordnung neu erstellen (nach dem Hinzufügen/Verschieben von Dateien)
# Exit 1 + „run the full suite“ bedeutet, dass eine Hub-Datei (tsconfig, package.json, …) oder eine
# nicht zugeordnete Quelldatei geändert wurde — der Selektor schlägt sicher fehl und überspringt niemals unbemerkt Tests.
# Vitest (MCP-Server, autoCombo, Cache)
npm run test:vitest
# E2E-Tests (erfordert Playwright)
npm run test:e2e
# E2E für Protokoll-Clients (MCP-Transporte, A2A)
npm run test:protocols:e2e
# Kompatibilitätstests für das Ökosystem
npm run test:ecosystem
# Coverage-Gate: 60 % Anweisungen/Zeilen/Funktionen/Verzweigungen
npm run test:coverage
npm run coverage:report
# Lint- und Formatierungsprüfung
npm run lint
npm run check
# Durch Gate geschützter Combo-Smoke-Test mit echten Upstream-Diensten (erfordert VPS-Zugriff + Guthaben bei echten Anbietern)
# Greift auf ECHTE Anbieter zu — verursacht geringe Kosten. Wird NIEMALS in CI ausgeführt. Wird ohne Gate ordnungsgemäß übersprungen.
# Erforderlich: Zugriff per ssh root@192.168.0.15 (bezieht einen schreibgeschützten DB-Snapshot vom VPS).
RUN_COMBO_LIVE=1 npm run test:combo:live
# Live-Smoke-Test für den Phase-3-VPS — reine Node-ESM-Skripte, die direkt auf den Live-Server .15 zugreifen.
# Erfordert: Zugriff per ssh root@192.168.0.15 (Combos werden per SSH sqlite erstellt/entfernt).
# Greift auf ECHTE Anbieter zu (geringe Kosten). Erstellt/löscht ausschließlich __live_test__*-Combos. Wird NIEMALS in CI ausgeführt.
# REQUIRE_API_KEY=false auf .15, daher ist kein API-Schlüssel erforderlich; COMBO_LIVE_BASE_URL / COMBO_LIVE_API_KEY werden jedoch berücksichtigt, falls gesetzt.
npm run test:combo:live:vps # 7 HTTP-Szenarien (Priorität/Round-Robin/gewichtet/Kosten/Fusion/automatisch + Zustand)
npm run test:combo:live:vps:failover # fügt ein echtes anbieterübergreifendes Failover-Szenario hinzu (insgesamt 8)
Hinweise zur Testabdeckung:
npm run test:coveragemisst die Quellcodeabdeckung für die Haupt-Unit-Test-Suite, schließttests/**aus und umfasstopen-sse/**- Pull Requests müssen das Coverage-Gate bei 60 %+ für Anweisungen/Zeilen/Funktionen/Verzweigungen halten
- Wenn ein PR Produktionscode in
src/,open-sse/,electron/oderbin/ändert, müssen im selben PR automatisierte Tests hinzugefügt oder aktualisiert werden npm run coverage:reportgibt den detaillierten Bericht für jede einzelne Datei aus dem letzten Coverage-Lauf ausnpm run test:coverage:legacybehält die ältere Metrik für historische Vergleiche bei- Siehe
docs/ops/COVERAGE_PLAN.mdfür den phasenweisen Plan zur Verbesserung der Testabdeckung
Anforderungen an Pull Requests
Verwende vor dem Öffnen eines PR den Golden Path für Beiträge, um die fokussierte Schleife für deine Änderungen auszuführen. Die vollständige Unit-Test-Suite (4 CI-Shards), Vitest, das Coverage-Gate von 60 %+ und der Produktions-Build liegen in der Verantwortung von CI — sie lokal auszuführen, liefert keine zusätzlichen Erkenntnisse, die dir die PR-Prüfungen nicht ohnehin liefern würden, und kann auf kleineren Rechnern den Host überlasten (#8084):
- Führe die Testdateien aus, die deine Änderung abdecken:
node --import tsx/esm --test tests/unit/<file>.test.ts - Führe
npm run lintaus - Füge im selben PR automatisierte Tests hinzu oder aktualisiere sie, wenn Produktionscode geändert wird
- Nenne die geänderten oder hinzugefügten Testdateien in der PR-Beschreibung, wenn Produktionscode geändert wurde
- Prüfe das SonarQube-Ergebnis im PR, wenn die Projekt-Secrets in CI konfiguriert sind
Aktueller Teststatus: 122 Unit-Test-Dateien mit Abdeckung für:
- Provider-Übersetzer und Formatkonvertierung
- Ratenbegrenzung, Circuit Breaker und Resilienz
- Semantischen Cache, Idempotenz und Fortschrittsverfolgung
- Datenbankoperationen und -schema (21 DB-Module)
- OAuth-Abläufe und Authentifizierung
- Validierung von API-Endpunkten (Zod v4)
- MCP-Server-Tools und Durchsetzung von Geltungsbereichen
- Speicher- und Skills-Systeme
Codestil
- ESLint — Vor dem Commit
npm run lintausführen - Prettier — Beim Commit automatisch über
lint-stagedformatiert (2 Leerzeichen, Semikolons, doppelte Anführungszeichen, 100 Zeichen Zeilenbreite, nachgestellte Kommas gemäß es5) - TypeScript — Der gesamte Code unter
src/verwendet.ts/.tsx;open-sse/verwendet.ts/.js; mit TSDoc dokumentieren (@param,@returns,@throws) - Kein
eval()— ESLint erzwingtno-eval,no-implied-eval,no-new-func - Zod-Validierung — Zod-v4-Schemas für die Validierung aller API-Eingaben verwenden
- Benennung: Dateien = camelCase/kebab-case, Komponenten = PascalCase, Konstanten = UPPER_SNAKE
Fehlerbehandlung / leere catch-Blöcke
Ein catch darf niemals unerklärt bleiben. Ordne es einer von zwei Kategorien zu (dies setzt
die strikte Regel „Fehler in SSE-Streams niemals stillschweigend verschlucken“ praktisch um):
-
Beabsichtigt (eigene Best-Effort-Bereinigung/Telemetrie) — ein Fehler ist hier zu erwarten und harmlos; füge einen einzeiligen Kommentar zur Begründung hinzu, ohne Logging (diese Konvention vermeidet störende Log-Ausgaben bei jeder Anfrage).
} catch {} // das Schließen eines bereits geschlossenen Controllers nach einem Client-Verbindungsabbruch ist zu erwarten -
Sollte protokolliert werden (externer/vom Aufrufer bereitgestellter Code oder das Verschlucken ändert den Kontrollfluss) — behalte den catch-Block bei (der Stream darf dadurch niemals unterbrochen werden), gib aber eine kontextbezogene
console.debug-/warn-Meldung aus, damit der Fehler auffindbar ist.} catch (e) { console.debug("[STREAM] Fehler im onFailure-Callback:", e); }
Anwendungsbeispiele findest du unter open-sse/utils/stream.ts und open-sse/utils/streamHandler.ts.
Project Structure
src/ # TypeScript (.ts / .tsx)
├── app/ # Next.js 16 App Router
│ ├── (dashboard)/ # Dashboard pages (23 sections)
│ ├── api/ # API routes (51 directories)
│ └── login/ # Auth pages (.tsx)
├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
├── lib/ # Core business logic (.ts)
│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
│ ├── acp/ # Agent Communication Protocol registry
│ ├── compliance/ # Compliance policy engine
│ ├── db/ # SQLite database layer (110 top-level modules + 130 migrations)
│ ├── memory/ # Persistent conversational memory
│ ├── oauth/ # OAuth providers, services, and utilities
│ ├── skills/ # Extensible skill framework
│ ├── usage/ # Usage tracking and cost calculation
│ └── localDb.ts # Re-export layer only — never add logic here
├── middleware/ # Request middleware (promptInjectionGuard)
├── mitm/ # MITM proxy (cert, DNS, target routing)
├── shared/
│ ├── components/ # React components (.tsx)
│ ├── constants/ # Provider definitions (329), MCP scopes, routing strategies
│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
│ └── validation/ # Zod v4 schemas
└── sse/ # SSE proxy pipeline
open-sse/ # @omniroute/open-sse workspace
├── executors/ # 89 executor implementation modules
├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
├── mcp-server/ # MCP server (107 tools, 3 transports, 32 scopes)
├── services/ # 178 top-level services (combo, autoCombo, rateLimitManager, etc.)
├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
├── transformer/ # Responses API transformer
└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
electron/ # Electron desktop app (cross-platform)
tests/
├── unit/ # Node.js test runner (122 test files)
├── integration/ # Integration tests
├── e2e/ # Playwright tests
├── security/ # Security tests
├── translator/ # Translator-specific tests
└── load/ # Load tests
docs/ # Documentation
├── ARCHITECTURE.md # System architecture
├── API_REFERENCE.md # All endpoints
├── USER_GUIDE.md # Provider setup, CLI integration
├── TROUBLESHOOTING.md # Common issues
├── MCP-SERVER.md # MCP server (107 tools)
├── A2A-SERVER.md # A2A agent protocol
├── AUTO-COMBO.md # Auto-combo engine
├── CLI-TOOLS.md # CLI tools integration
├── COVERAGE_PLAN.md # Test coverage improvement plan
├── openapi.yaml # OpenAPI specification
└── adr/ # Architecture Decision Records
Hinzufügen eines neuen Providers
Schritt 1: Provider-Konstanten registrieren
Zu src/shared/constants/providers.ts hinzufügen — wird beim Laden des Moduls mit Zod validiert.
Schritt 2: Executor hinzufügen (falls benutzerdefinierte Logik erforderlich ist)
Einen Executor in open-sse/executors/your-provider.ts erstellen, der den Basis-Executor erweitert.
Schritt 3: Translator hinzufügen (falls kein OpenAI-Format verwendet wird)
Request-/Response-Translator in open-sse/translator/ erstellen.
Schritt 4: OAuth-Konfiguration hinzufügen (falls OAuth-basiert)
OAuth-Anmeldedaten in src/lib/oauth/constants/oauth.ts und den Service in src/lib/oauth/services/ hinzufügen.
Wenn der Upstream-Provider eine öffentliche OAuth-client_id/ein öffentliches OAuth-Secret oder einen Firebase-Web-API-Schlüssel innerhalb seiner öffentlichen CLI bzw. seines Browser-Bundles bereitstellt, darf dieser nicht als Stringliteral eingebettet werden. resolvePublicCred() aus open-sse/utils/publicCreds.ts verwenden und einen maskierten Byte-Eintrag zu EMBEDDED_DEFAULTS hinzufügen. Der vollständige verpflichtende Workflow ist in docs/security/PUBLIC_CREDS.md dokumentiert.
In Handlern/Executors müssen Fehlermeldungen, die den Client erreichen, über buildErrorBody() / sanitizeErrorMessage() aus open-sse/utils/error.ts verarbeitet werden — niemals unverarbeitete Werte aus err.stack oder err.message in einen Response-Body einfügen. Siehe docs/security/ERROR_SANITIZATION.md.
Schritt 5: Modelle registrieren
Modelldefinitionen in open-sse/config/providerRegistry.ts hinzufügen.
Schritt 6: Tests hinzufügen
Unit-Tests in tests/unit/ schreiben, die mindestens Folgendes abdecken:
- Provider-Registrierung
- Request-/Response-Übersetzung
- Fehlerbehandlung
Pull-Request-Checkliste
- Tests erfolgreich (
npm test) - Linting erfolgreich (
npm run lint) - Build erfolgreich (
npm run build) - TypeScript-Typen für neue öffentliche Funktionen und Schnittstellen hinzugefügt
- Keine hartcodierten Geheimnisse oder Fallback-Werte
- Öffentliche Upstream-Zugangsdaten über
resolvePublicCred()eingebettet (siehedocs/security/PUBLIC_CREDS.md), niemals als Literale - Fehlerantworten werden über
buildErrorBody()/sanitizeErrorMessage()geleitet – keine unverarbeiteten Stacktraces in Antworttexten (siehedocs/security/ERROR_SANITIZATION.md) - Shell-Befehle (
exec/spawn) übergeben Laufzeitwerte überenv, nicht über String-Interpolation - Alle Eingaben mit Zod-Schemas validiert
- Changelog-Fragment für benutzersichtbare Änderungen unter
changelog.d/{features|fixes|maintenance}/<PR>-<slug>.mdhinzugefügt (siehechangelog.d/README.md) –CHANGELOG.mdnicht direkt bearbeiten; Fragmente werden zum Veröffentlichungszeitpunkt zusammengeführt und verursachen niemals Konflikte zwischen PRs - Dokumentation aktualisiert (falls zutreffend)
- Keine neuen CodeQL- / Secret-Scanning-Warnungen ausgelöst oder jede einzelne mit einer technischen Begründung unter Verweis auf das relevante Dokument unter
docs/security/verworfen - Routen, die untergeordnete Prozesse starten (
/api/mcp/,/api/cli-tools/runtime/), insrc/server/authz/routeGuard.tsalsisLocalOnlyPath()klassifiziert – siehe Strikte Regel Nr. 15 - Keine
Co-Authored-By-Trailer in Commit-Nachrichten – Commits dürfen ausschließlich unter der Git-Identität des Repository-Eigentümers erscheinen (Strikte Regel Nr. 16)
Releasing
Releases are managed via the /generate-release workflow. When a new GitHub Release is created, the package is automatically published to npm via GitHub Actions.
Hilfe erhalten
- Architektur: Siehe
docs/architecture/ARCHITECTURE.md - API-Referenz: Siehe
docs/reference/API_REFERENCE.md - Sicherheitsdokumentation:
docs/security/CLI_TOKEN.md,docs/security/ROUTE_GUARD_TIERS.md,docs/security/ERROR_SANITIZATION.md,docs/security/PUBLIC_CREDS.md - Betriebsdokumentation:
docs/ops/SQLITE_RUNTIME.md - Issues: github.com/diegosouzapw/OmniRoute/issues
- ADRs: Siehe
docs/adr/für Aufzeichnungen zu Architekturentscheidungen