Files
OmniRoute/docs/i18n/pl/CONTRIBUTING.md

19 KiB
Raw Blame History

Współtworzenie OmniRoute

Dziękujemy za zainteresowanie współtworzeniem projektu! Ten przewodnik zawiera wszystko, czego potrzebujesz, aby zacząć.


Konfiguracja środowiska deweloperskiego

Wymagania wstępne

  • Node.js >=22.22.3 <23, lub >=24.0.0 <27 (zalecane: 24 LTS)
  • npm 10+
  • Git

Klonowanie i instalacja

git clone https://github.com/diegosouzapw/OmniRoute.git
cd OmniRoute
npm install

Zmienne środowiskowe

# Create your .env from the template
cp .env.example .env

# Generate required secrets
echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env

Kluczowe zmienne na potrzeby developmentu:

Zmienna Domyślna (dev) Opis
PORT 20128 Port serwera
NEXT_PUBLIC_BASE_URL http://localhost:20128 Bazowy URL frontendu
JWT_SECRET (wygeneruj powyżej) Sekret do podpisywania JWT
INITIAL_PASSWORD CHANGEME Hasło pierwszego logowania
APP_LOG_LEVEL info Poziom szczegółowości logów

Ustawienia dashboardu

Dashboard udostępnia przełączniki UI dla funkcji, które można też konfigurować przez zmienne środowiskowe:

Lokalizacja ustawienia Przełącznik Opis
Settings → Advanced Debug Mode Włącz logi debugowania żądań (UI)
Settings → General Sidebar Visibility Pokaż/ukryj sekcje paska bocznego

Te ustawienia są przechowywane w bazie danych i utrzymują się po restarcie, nadpisując domyślne wartości env var, gdy są ustawione.

Uruchamianie lokalnie

# Development mode (hot reload)
npm run dev

# Production build
npm run build    # next build → .build/next/ then assembleStandalone → dist/
npm run start

# Release build (clean rebuild + HEAD sentinel — required for deploy)
npm run build:release   # rm -rf .build dist && build + writes dist/BUILD_SHA

# Common port configuration
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev

Układ artefaktów builda

Katalog Zawartość Śledzony
src/ Kod źródłowy aplikacji (TypeScript / TSX) Tak
.build/ Pliki pośrednie — wyjście next build (gitignored, distDir = .build/next) Nie
dist/ Pakiet do dystrybucji — składany przez assembleStandalone (gitignored) Nie

Pipeline builda to jedno przejście:

npm run build
  └─ next build → .build/next/standalone  (Next.js output)
  └─ assembleStandalone()                 (copies standalone + static + public + native assets)
       └─ output: dist/                   (server.js, .next/static/, public/, node_modules/)

npm run build:release dodatkowo najpierw czyści oba katalogi i zapisuje dist/BUILD_SHA (= git rev-parse --short HEAD) jako sentinel integralności deployu.

Uwaga o deployu VPS: zdalny katalog obrazu /usr/lib/node_modules/omniroute/app/ pozostaje bez zmian. Skille deployu robią rsync zawartości dist/ do tego katalogu. Zmieniła się tylko ścieżka wyjścia builda w repozytorium (app/dist/).

Domyślne URL-e:

  • Dashboard: http://localhost:20128/dashboard
  • API: http://localhost:20128/v1

Przepływ pracy Git

⚠️ NIGDY nie commituj bezpośrednio do main. Zawsze używaj branchy funkcyjnych.

Baza PR: celuj w aktywny branch release/vX.Y.Z (nie main). Zobacz docs/ops/BRANCHING_MODEL.md dla modelu release-per-branch + tag-at-ship.

# Branch from the active release tip (example: release/v3.8.49)
git fetch origin
git checkout -b feat/your-feature-name origin/release/v3.8.49
# ... make changes ...
git commit -m "feat: describe your change"
git push -u origin feat/your-feature-name
# Open a Pull Request with base = release/v3.8.49

Nazewnictwo branchy

Prefiks Przeznaczenie
feat/ Nowe funkcje
fix/ Poprawki błędów
refactor/ Restrukturyzacja kodu
docs/ Zmiany w dokumentacji
test/ Dodawanie/poprawki testów
chore/ Tooling, CI, zależności

Komunikaty commitów

Stosuj 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.


Uruchamianie testów

# All tests (unit + vitest + ecosystem + e2e)
npm run test:all

# Single test file (Node.js native test runner — most tests use this)
node --import tsx/esm --test tests/unit/your-file.test.ts

# Vitest (MCP server, autoCombo, cache)
npm run test:vitest

# E2E tests (requires Playwright)
npm run test:e2e

# Protocol clients E2E (MCP transports, A2A)
npm run test:protocols:e2e

# Ecosystem compatibility tests
npm run test:ecosystem

# Coverage gate: 60% statements/lines/functions/branches
npm run test:coverage
npm run coverage:report

# Lint + format check
npm run lint
npm run check

# Gated real-upstream combo smoke (requires VPS access + real provider credits)
# Hits REAL providers — costs a little. NEVER runs in CI. Skips cleanly without the gate.
# Needs: ssh root@192.168.0.15 access (sources a read-only DB snapshot from the VPS).
RUN_COMBO_LIVE=1 npm run test:combo:live

# Phase-3 VPS live smoke — plain Node ESM scripts, hit the live .15 server directly.
# Requires: ssh root@192.168.0.15 access (combos created/torn down via SSH sqlite).
# Hits REAL providers (small cost). Creates/deletes only __live_test__* combos. NEVER runs in CI.
# REQUIRE_API_KEY=false on .15 so no API key needed, but honors COMBO_LIVE_BASE_URL / COMBO_LIVE_API_KEY if set.
npm run test:combo:live:vps              # 7 HTTP scenarios (priority/round-robin/weighted/cost/fusion/auto + health)
npm run test:combo:live:vps:failover     # adds a real cross-provider failover scenario (8 total)

Uwagi o coverage:

  • npm run test:coverage mierzy pokrycie źródeł głównego pakietu testów jednostkowych, wyklucza tests/** i obejmuje open-sse/**
  • Pull requesty muszą utrzymywać próg coverage na poziomie 60%+ statements/lines/functions/branches
  • Jeśli PR zmienia kod produkcyjny w src/, open-sse/, electron/ lub bin/, musi dodać lub zaktualizować automatyczne testy w tym samym PR
  • npm run coverage:report wypisuje szczegółowy raport plik po pliku z ostatniego uruchomienia coverage
  • npm run test:coverage:legacy zachowuje starszą metrykę do porównań historycznych
  • Zobacz docs/ops/COVERAGE_PLAN.md dla etapowego planu poprawy coverage

Wymagania wobec pull requestów

Przed otwarciem PR uruchom skupioną pętlę dla tego, co zmieniłeś. Pełny pakiet testów jednostkowych (4 shardy CI), Vitest, próg coverage 60%+ oraz build produkcyjny to odpowiedzialność CI — lokalne ich uruchamianie nie daje sygnału, którego nie dadzą już checki PR, a na mniejszych maszynach może nasycić host (#8084):

  • Uruchom pliki testów obejmujące Twoją zmianę: node --import tsx/esm --test tests/unit/<file>.test.ts
  • Uruchom npm run lint
  • Dołącz lub zaktualizuj automatyczne testy w tym samym PR przy każdej zmianie kodu produkcyjnego
  • W opisie PR wymień zmienione lub dodane pliki testów, gdy zmieniał się kod produkcyjny
  • Sprawdź wynik SonarQube na PR, gdy sekrety projektu są skonfigurowane w CI

Aktualny status testów: 122 pliki testów jednostkowych obejmujące:

  • Translatory providerów i konwersję formatów
  • Rate limiting, circuit breaker i resilience
  • Semantic cache, idempotency, śledzenie postępu
  • Operacje na bazie danych i schemat (21 modułów DB)
  • Przepływy OAuth i uwierzytelnianie
  • Walidację endpointów API (Zod v4)
  • Narzędzia serwera MCP i egzekwowanie scopeów
  • Systemy Memory i Skills

Styl kodu

  • ESLint — Uruchom npm run lint przed commitem
  • Prettier — Autoformatowanie przez lint-staged przy commicie (2 spacje, średniki, podwójne cudzysłowy, szerokość 100 znaków, przecinki końcowe es5)
  • TypeScript — Cały kod w src/ używa .ts/.tsx; open-sse/ używa .ts/.js; dokumentuj przez TSDoc (@param, @returns, @throws)
  • Bez eval() — ESLint egzekwuje no-eval, no-implied-eval, no-new-func
  • Walidacja Zod — Używaj schematów Zod v4 do walidacji wszystkich wejść API
  • Nazewnictwo: Pliki = camelCase/kebab-case, komponenty = PascalCase, stałe = UPPER_SNAKE

Obsługa błędów / puste bloki catch

Nigdy nie zostawiaj catch bez wyjaśnienia. Przypisz go do jednego z dwóch kubełków (operacjonalizuje twardą regułę „nigdy nie połykaj po cichu błędów w strumieniach SSE”):

  • Zamierzone (nasze własne best-effort cleanup/telemetry) — awaria tutaj jest oczekiwana i nieszkodliwa; dodaj jednoliniowy komentarz z uzasadnieniem, bez logowania (logowanie przy każdym żądaniu to szum, którego ta konwencja unika).

    } catch {} // closing an already-closed controller after client disconnect is expected
    
  • Należy zalogować (kod zewnętrzny/dostarczony przez wywołującego, albo połykanie zmienia flow sterowania) — zachowaj catch (nigdy nie pozwól mu przerwać streamu), ale wyemituj kontekstowy console.debug/warn, aby awaria była wykrywalna.

    } catch (e) {
      console.debug("[STREAM] onFailure callback error:", e);
    }
    

Zobacz open-sse/utils/stream.ts i open-sse/utils/streamHandler.ts jako zastosowane przykłady.


Struktura projektu

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 (21 modules + 16 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 (177), MCP scopes, 14 routing strategies
│   ├── utils/              # Circuit breaker, sanitizer, auth helpers
│   └── validation/         # Zod v4 schemas
└── sse/                    # SSE proxy pipeline

open-sse/                   # @omniroute/open-sse workspace
├── executors/              # 14 provider-specific request executors
├── handlers/               # 11 request handlers (chat, responses, embeddings, images, etc.)
├── mcp-server/             # MCP server (25 tools, 3 transports, 10 scopes)
├── services/               # 36+ 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 (1,574 test files)
├── integration/            # Integration tests
├── e2e/                    # Playwright tests
├── security/               # Security tests
├── translator/             # Translator-specific tests
└── load/                   # Load tests

docs/
├── adr/                     # Architecture Decision Records
├── architecture/            # System architecture & resilience
├── comparison/              # OmniRoute vs alternatives
├── compression/             # Compression guides & rules
├── dev/                     # Development guides
├── diagrams/                # Architecture diagrams
├── frameworks/              # MCP, A2A, OpenCode, Memory, Skills
├── guides/                  # User guide, Docker, setup, troubleshooting
├── i18n/                    # Internationalized README translations
├── marketing/               # Marketing materials
├── ops/                     # Deployment, proxy, coverage, releases
├── providers/               # Provider-specific docs
├── reference/               # API reference, env vars, CLI tools, free tiers
├── releases/                # Release notes
├── routing/                 # Auto-combo engine, reasoning replay
├── screenshots/             # Dashboard screenshots
├── security/                # Guardrails, compliance, stealth, tokens
└── specs/                   # Design specs

Dodawanie nowego providera

Krok 1: Zarejestruj stałe providera

Dodaj do src/shared/constants/providers.ts — walidacja Zod przy ładowaniu modułu.

Krok 2: Dodaj executor (jeśli potrzebna logika niestandardowa)

Utwórz executor w open-sse/executors/your-provider.ts rozszerzający bazowy executor.

Krok 3: Dodaj translator (jeśli format inny niż OpenAI)

Utwórz translatory request/response w open-sse/translator/.

Krok 4: Dodaj konfigurację OAuth (jeśli oparty o OAuth)

Dodaj poświadczenia OAuth w src/lib/oauth/constants/oauth.ts oraz serwis w src/lib/oauth/services/.

Jeśli upstream provider dystrybuuje publiczny OAuth client_id/secret lub klucz Firebase Web API w swoim publicznym CLI / pakiecie przeglądarkowym, nie osadzaj go jako literału stringowego. Użyj resolvePublicCred() z open-sse/utils/publicCreds.ts i dodaj zamaskowany wpis bajtowy do EMBEDDED_DEFAULTS. Pełny obowiązkowy workflow jest udokumentowany w docs/security/PUBLIC_CREDS.md.

Wewnątrz handlers/executors komunikaty błędów docierające do klienta muszą przechodzić przez buildErrorBody() / sanitizeErrorMessage() z open-sse/utils/error.ts — nigdy nie umieszczaj surowego err.stack ani err.message w ciele Response. Zobacz docs/security/ERROR_SANITIZATION.md.

Krok 5: Zarejestruj modele

Dodaj definicje modeli w open-sse/config/providerRegistry.ts.

Krok 6: Dodaj testy

Napisz testy jednostkowe w tests/unit/ obejmujące co najmniej:

  • Rejestrację providera
  • Translację request/response
  • Obsługę błędów

Checklista pull requesta

  • Testy przechodzą (npm test)
  • Linting przechodzi (npm run lint)
  • Build się udaje (npm run build)
  • Dodane typy TypeScript dla nowych publicznych funkcji i interfejsów
  • Brak zahardkodowanych sekretów lub wartości fallback
  • Publiczne poświadczenia upstream osadzone przez resolvePublicCred() (zobacz docs/security/PUBLIC_CREDS.md), nigdy jako literały
  • Odpowiedzi błędów idą przez buildErrorBody() / sanitizeErrorMessage() — bez surowych stack traceów w ciałach odpowiedzi (zobacz docs/security/ERROR_SANITIZATION.md)
  • Komendy powłoki (exec / spawn) przekazują wartości runtime przez env, nie przez interpolację stringów
  • Wszystkie wejścia walidowane schematami Zod
  • Dodany fragment changelogu w changelog.d/{features|fixes|maintenance}/<PR>-<slug>.md dla zmian widocznych dla użytkownika (zobacz changelog.d/README.md) — nie edytuj CHANGELOG.md bezpośrednio; fragmenty są agregowane w czasie release i nigdy nie kolidują między PR-ami
  • Zaktualizowana dokumentacja (jeśli dotyczy)
  • Brak nowych alertów CodeQL / Secret-Scanning, albo każdy odrzucony z technicznym uzasadnieniem odwołującym się do odpowiedniego dokumentu w docs/security/
  • Trasy uruchamiające procesy potomne (/api/mcp/, /api/cli-tools/runtime/) sklasyfikowane jako isLocalOnlyPath() w src/server/authz/routeGuard.ts — zobacz Hard Rule #15
  • Brak trailerów Co-Authored-By w komunikatach commitów — commity muszą figurować wyłącznie pod tożsamością Git właściciela repozytorium (Hard Rule #16)

Wydawanie wersji

Wydania są zarządzane przez workflow /generate-release. Gdy tworzony jest nowy GitHub Release, pakiet jest automatycznie publikowany do npm przez GitHub Actions.

Do deployów VPS używaj npm run build:release (nie npm run build) — wykonuje czysty rebuild, składa pakiet do dist/ i zapisuje sentinel dist/BUILD_SHA. Następnie użyj skilli /deploy-vps-*-cc, które robią rsync dist/ do zdalnego katalogu app/.


Pomoc