docs: merge duplicate guides (troubleshooting, chatgpt-web codex, docker channels, memory backend)

This commit is contained in:
backryun
2026-08-12 12:30:40 -03:00
parent 156d118bc2
commit b49d5f6a98
15 changed files with 398 additions and 1382 deletions

View File

@@ -9,7 +9,9 @@ It describes each gate, what it validates, which CI job it runs in, whether it u
a ratchet baseline or a pass/fail policy, and whether it blocks the build or is advisory.
For a short summary and the allowlist policy, see the "Quality Gates & Ratchets" section
in `CLAUDE.md`.
in `CLAUDE.md`. For the critical assessment, maturity classification, and tool-agnostic
replication plan of the same system, see the
[Quality Gate Playbook](../ops/QUALITY_GATE_PLAYBOOK.md).
---

View File

@@ -888,3 +888,229 @@ To leave it off, simply keep `autoSummarize` at its default (`false`).
0 3 * * * curl -X POST http://localhost:20128/api/memory/summarize \
-H "Authorization: Bearer $OMNIROUTE_KEY"
```
---
## MemoryBackend Provider Pattern
> **Source of truth:** `src/lib/memory/backend.ts`, `src/lib/memory/genericBackend.ts`, `src/lib/memory/manager.ts`
> **Tests:** `src/lib/memory/__tests__/generic-backend.test.ts`
The MemoryBackend provider pattern introduces a **pluggable backend abstraction layer** over the existing memory engine. Instead of being tied to a single storage implementation, the memory system now supports multiple backends (SQLite, Obsidian, Notion, custom HTTP backends) with configurable primary/fallback routing.
### Architecture
```
┌──────────────────────────────────────────────────────────┐
│ API Routes │
│ (src/app/api/memory/route.ts) │
└──────────────────────┬───────────────────────────────────┘
┌──────────────────────▼───────────────────────────────────┐
│ MemoryManager │
│ Singleton orchestrator (manager.ts) │
│ │
│ Primary ──► Backend A (e.g. SQLite) │
│ Fallback ─► Backend B (e.g. Obsidian) │
│ Backend C (e.g. Notion via GenericBackend) │
└──────────────────────┬───────────────────────────────────┘
┌──────────────┼──────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌──────────────────┐
│ SQLite │ │ Obsidian │ │ GenericMemory │
│ Backend │ │ Backend │ │ Backend (HTTP) │
└────────────┘ └────────────┘ └──────────────────┘
```
#### Core Interface (`backend.ts`)
Every backend must implement the `MemoryBackend` interface:
```typescript
interface MemoryBackend {
readonly id: string;
readonly displayName: string;
// CRUD
create(input: CreateMemoryInput): Promise<Memory>;
get(id: string): Promise<Memory | null>;
update(id: string, updates: Partial<...>): Promise<boolean>;
delete(id: string): Promise<boolean>;
list(filter: MemoryFilter): Promise<{ data: Memory[]; total: number; byType: Record<string, number> }>;
// Search
search(config: SearchConfig): Promise<Memory[]>;
// Health
health(): Promise<HealthCheckResult>;
// Lifecycle (optional)
initialize?(): Promise<void>;
shutdown?(): Promise<void>;
}
```
#### MemoryManager (`manager.ts`)
Singleton orchestrator that:
- **Registers** backends via `register(backend)` — called at boot from `index.ts`
- **Configures** primary + fallback via `configure(primary, fallbacks)`
- **Routes** CRUD/search to the primary, with fallback chain on failure
- **Health checks** all backends periodically
**Fallback behavior:**
| Operation | Primary | Fallbacks |
| --------- | -------------------- | ----------------------- |
| `create` | ✅ Primary only | ❌ |
| `get` | ✅ Try primary first | ✅ Fallback if null |
| `update` | ✅ Primary only | ✅ Fire-and-forget sync |
| `delete` | ✅ Primary only | ✅ Fire-and-forget sync |
| `list` | ✅ Primary only | ❌ |
| `search` | ✅ Primary first | ✅ Fallback on error |
#### GenericMemoryBackend (`genericBackend.ts`)
A generic HTTP connector that adapts any REST API into a MemoryBackend. Useful for:
- **Notion** — connect via Notion API
- **Obsidian** — connect via Obsidian Local REST API
- **Custom backends** — any service that exposes a RESTful memory API
**Configuration:**
```typescript
interface GenericBackendConfig {
baseUrl: string; // Base URL of the backend API
apiKey?: string; // Bearer token for auth
headers?: Record<string, string>; // Custom HTTP headers
timeout?: number; // Request timeout (default: 30000ms)
backendType?: string; // For logging
// Endpoint overrides (defaults use REST conventions)
endpoints?: {
search?: string; // default: "/memories/search"
create?: string; // default: "/memories"
list?: string; // default: "/memories"
get?: string; // default: "/memories/{id}"
update?: string; // default: "/memories/{id}"
delete?: string; // default: "/memories/{id}"
health?: string; // default: "/health"
};
// Query parameter name mappings
queryParams?: {
query?/apiKeyId?/limit?/offset?/strategy?/maxTokens?/type?/sessionId?/orderBy?/orderDir?/options?
};
// Path parameter name mappings
pathParams?: {
id?/memoryId?
};
}
```
**Known backends** are pre-configured in `KNOWN_BACKENDS`:
```typescript
createKnownBackend("obsidian"); // → GenericMemoryBackend pointed at localhost:27123
createKnownBackend("notion"); // → GenericMemoryBackend pointed at api.notion.com/v1
```
#### Built-in Backends
##### SQLiteBackend (`sqliteBackend.ts`)
The default primary backend. Wraps the existing SQLite-based memory store using `src/lib/memory/store.ts`. Automatically registered at boot.
```typescript
import { sqliteBackend } from "./sqliteBackend";
memoryManager.register(sqliteBackend);
```
##### ObsidianBackend (`obsidianBackend.ts`)
Wraps the existing Obsidian integration (`src/lib/memory/obsidianBackend.ts`). Connects to an Obsidian vault via the Obsidian Local REST API.
### Settings
Memory backend settings are stored in the app settings table and managed via `src/lib/memory/settings.ts`:
| Setting | Env/Config Key | Default | Description |
| ----------------- | ------------------------ | ---------- | ---------------------------- |
| Primary backend | `memoryPrimaryBackend` | `"sqlite"` | ID of the primary backend |
| Fallback backends | `memoryFallbackBackends` | `[]` | Ordered fallback backend IDs |
| Backend configs | `memoryBackendConfigs` | `{}` | Per-backend config overrides |
Settings are normalized via `normalizeMemorySettings()` and cached at `getMemorySettings()`.
### Initialization Flow
```
App bootstrap
→ index.ts imports (side-effect): registers SQLiteBackend
→ initMemoryBackends() called from app lifecycle:
1. Load settings (getMemorySettings)
2. Configure primary + fallback
3. Initialize all backends (health check)
4. Ready for requests
```
### Adding a New Backend
1. **Implement `MemoryBackend`** interface in `src/lib/memory/<name>Backend.ts`
2. **Export** from `src/lib/memory/index.ts`
3. **Register** with `memoryManager.register(yourBackend)` at boot
4. **Configure** via settings: set `memoryPrimaryBackend` to your backend ID
5. **Test** with `src/lib/memory/__tests__/generic-backend.test.ts` as reference
#### Example: Brain Backend
```typescript
import { createGenericMemoryBackend } from "./genericBackend";
const brainBackend = createGenericMemoryBackend("brain", "BK-Brain", {
baseUrl: process.env.BRAIN_API_URL || "http://localhost:9099",
apiKey: process.env.BRAIN_API_KEY,
endpoints: {
search: "/api/memory/search",
create: "/api/memory",
health: "/api/health",
},
});
memoryManager.register(brainBackend);
```
### Verification
#### Unit tests
```bash
npx vitest run src/lib/memory/__tests__/generic-backend.test.ts --reporter=verbose
```
Expected output: **26 tests, all passing** covering:
- Constructor (2)
- Health check (4) — success, failure 500, network error, latency
- Initialize (2) — success, failure
- Create (2) — default endpoint, custom endpoint
- Get (4) — success, 404 → null, non-404 throw, custom path params
- Update (2) — success, 404 → false
- Delete (2) — success, 404 → false
- List (2) — query params, custom param names
- Search (3) — query params, custom endpoint, options serialization
- Auth headers (2) — Bearer token, custom headers
- Factory (1)
#### Type check
```bash
npm run typecheck:core
```
Expected: **0 errors**.

View File

@@ -1,228 +0,0 @@
---
title: "MemoryBackend Provider Pattern"
version: 3.8.49
lastUpdated: 2026-07-28
---
# MemoryBackend Provider Pattern
> **Source of truth:** `src/lib/memory/backend.ts`, `src/lib/memory/genericBackend.ts`, `src/lib/memory/manager.ts`
> **Tests:** `src/lib/memory/__tests__/generic-backend.test.ts`
The MemoryBackend provider pattern introduces a **pluggable backend abstraction layer** over the existing memory engine. Instead of being tied to a single storage implementation, the memory system now supports multiple backends (SQLite, Obsidian, Notion, custom HTTP backends) with configurable primary/fallback routing.
## Architecture
```
┌──────────────────────────────────────────────────────────┐
│ API Routes │
│ (src/app/api/memory/route.ts) │
└──────────────────────┬───────────────────────────────────┘
┌──────────────────────▼───────────────────────────────────┐
│ MemoryManager │
│ Singleton orchestrator (manager.ts) │
│ │
│ Primary ──► Backend A (e.g. SQLite) │
│ Fallback ─► Backend B (e.g. Obsidian) │
│ Backend C (e.g. Notion via GenericBackend) │
└──────────────────────┬───────────────────────────────────┘
┌──────────────┼──────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌──────────────────┐
│ SQLite │ │ Obsidian │ │ GenericMemory │
│ Backend │ │ Backend │ │ Backend (HTTP) │
└────────────┘ └────────────┘ └──────────────────┘
```
### Core Interface (`backend.ts`)
Every backend must implement the `MemoryBackend` interface:
```typescript
interface MemoryBackend {
readonly id: string;
readonly displayName: string;
// CRUD
create(input: CreateMemoryInput): Promise<Memory>;
get(id: string): Promise<Memory | null>;
update(id: string, updates: Partial<...>): Promise<boolean>;
delete(id: string): Promise<boolean>;
list(filter: MemoryFilter): Promise<{ data: Memory[]; total: number; byType: Record<string, number> }>;
// Search
search(config: SearchConfig): Promise<Memory[]>;
// Health
health(): Promise<HealthCheckResult>;
// Lifecycle (optional)
initialize?(): Promise<void>;
shutdown?(): Promise<void>;
}
```
### MemoryManager (`manager.ts`)
Singleton orchestrator that:
- **Registers** backends via `register(backend)` — called at boot from `index.ts`
- **Configures** primary + fallback via `configure(primary, fallbacks)`
- **Routes** CRUD/search to the primary, with fallback chain on failure
- **Health checks** all backends periodically
**Fallback behavior:**
| Operation | Primary | Fallbacks |
| --------- | -------------------- | ----------------------- |
| `create` | ✅ Primary only | ❌ |
| `get` | ✅ Try primary first | ✅ Fallback if null |
| `update` | ✅ Primary only | ✅ Fire-and-forget sync |
| `delete` | ✅ Primary only | ✅ Fire-and-forget sync |
| `list` | ✅ Primary only | ❌ |
| `search` | ✅ Primary first | ✅ Fallback on error |
### GenericMemoryBackend (`genericBackend.ts`)
A generic HTTP connector that adapts any REST API into a MemoryBackend. Useful for:
- **Notion** — connect via Notion API
- **Obsidian** — connect via Obsidian Local REST API
- **Custom backends** — any service that exposes a RESTful memory API
**Configuration:**
```typescript
interface GenericBackendConfig {
baseUrl: string; // Base URL of the backend API
apiKey?: string; // Bearer token for auth
headers?: Record<string, string>; // Custom HTTP headers
timeout?: number; // Request timeout (default: 30000ms)
backendType?: string; // For logging
// Endpoint overrides (defaults use REST conventions)
endpoints?: {
search?: string; // default: "/memories/search"
create?: string; // default: "/memories"
list?: string; // default: "/memories"
get?: string; // default: "/memories/{id}"
update?: string; // default: "/memories/{id}"
delete?: string; // default: "/memories/{id}"
health?: string; // default: "/health"
};
// Query parameter name mappings
queryParams?: {
query?/apiKeyId?/limit?/offset?/strategy?/maxTokens?/type?/sessionId?/orderBy?/orderDir?/options?
};
// Path parameter name mappings
pathParams?: {
id?/memoryId?
};
}
```
**Known backends** are pre-configured in `KNOWN_BACKENDS`:
```typescript
createKnownBackend("obsidian"); // → GenericMemoryBackend pointed at localhost:27123
createKnownBackend("notion"); // → GenericMemoryBackend pointed at api.notion.com/v1
```
### Built-in Backends
#### SQLiteBackend (`sqliteBackend.ts`)
The default primary backend. Wraps the existing SQLite-based memory store using `src/lib/memory/store.ts`. Automatically registered at boot.
```typescript
import { sqliteBackend } from "./sqliteBackend";
memoryManager.register(sqliteBackend);
```
#### ObsidianBackend (`obsidianBackend.ts`)
Wraps the existing Obsidian integration (`src/lib/memory/obsidianBackend.ts`). Connects to an Obsidian vault via the Obsidian Local REST API.
## Settings
Memory backend settings are stored in the app settings table and managed via `src/lib/memory/settings.ts`:
| Setting | Env/Config Key | Default | Description |
| ----------------- | ------------------------ | ---------- | ---------------------------- |
| Primary backend | `memoryPrimaryBackend` | `"sqlite"` | ID of the primary backend |
| Fallback backends | `memoryFallbackBackends` | `[]` | Ordered fallback backend IDs |
| Backend configs | `memoryBackendConfigs` | `{}` | Per-backend config overrides |
Settings are normalized via `normalizeMemorySettings()` and cached at `getMemorySettings()`.
## Initialization Flow
```
App bootstrap
→ index.ts imports (side-effect): registers SQLiteBackend
→ initMemoryBackends() called from app lifecycle:
1. Load settings (getMemorySettings)
2. Configure primary + fallback
3. Initialize all backends (health check)
4. Ready for requests
```
## Adding a New Backend
1. **Implement `MemoryBackend`** interface in `src/lib/memory/<name>Backend.ts`
2. **Export** from `src/lib/memory/index.ts`
3. **Register** with `memoryManager.register(yourBackend)` at boot
4. **Configure** via settings: set `memoryPrimaryBackend` to your backend ID
5. **Test** with `src/lib/memory/__tests__/generic-backend.test.ts` as reference
### Example: Brain Backend
```typescript
import { createGenericMemoryBackend } from "./genericBackend";
const brainBackend = createGenericMemoryBackend("brain", "BK-Brain", {
baseUrl: process.env.BRAIN_API_URL || "http://localhost:9099",
apiKey: process.env.BRAIN_API_KEY,
endpoints: {
search: "/api/memory/search",
create: "/api/memory",
health: "/api/health",
},
});
memoryManager.register(brainBackend);
```
## Verification
### Unit tests
```bash
npx vitest run src/lib/memory/__tests__/generic-backend.test.ts --reporter=verbose
```
Expected output: **26 tests, all passing** covering:
- Constructor (2)
- Health check (4) — success, failure 500, network error, latency
- Initialize (2) — success, failure
- Create (2) — default endpoint, custom endpoint
- Get (4) — success, 404 → null, non-404 throw, custom path params
- Update (2) — success, 404 → false
- Delete (2) — success, 404 → false
- List (2) — query params, custom param names
- Search (3) — query params, custom endpoint, options serialization
- Auth headers (2) — Bearer token, custom headers
- Factory (1)
### Type check
```bash
npm run typecheck:core
```
Expected: **0 errors**.

View File

@@ -201,7 +201,7 @@ Round-robin cycles through providers in order. Auto-combo **scores each provider
- **[Connect a Provider](./PROVIDERS-GUIDE.md)** — Add your first AI provider
- **[Free Tiers Guide](./FREE-TIERS-GUIDE.md)** — Get free AI with no credit card
- **[Troubleshooting](./TROUBLESHOOTING.md)** — Fix common issues
- **[Troubleshooting](../guides/TROUBLESHOOTING.md)** — Fix common issues
- **[Technical Reference](../routing/AUTO-COMBO.md)** — Deep dive into the scoring algorithm
---

View File

@@ -272,5 +272,5 @@ No catch! Providers offer free tiers to attract users. OmniRoute just makes it e
- **[Auto-Combo Guide](./AUTO-COMBO-GUIDE.md)** — Let OmniRoute pick the best AI for you
- **[Providers Guide](./PROVIDERS-GUIDE.md)** — Connect more providers
- **[Troubleshooting](./TROUBLESHOOTING.md)** — Fix common issues
- **[Troubleshooting](../guides/TROUBLESHOOTING.md)** — Fix common issues
- **[Free Tiers Reference](../reference/FREE_TIERS.md)** — Full list of free tiers

View File

@@ -237,5 +237,5 @@ Go to Providers → click on the provider → click **Disconnect**.
- **[Auto-Combo Guide](./AUTO-COMBO-GUIDE.md)** — Let OmniRoute pick the best AI for you
- **[Free Tiers Guide](./FREE-TIERS-GUIDE.md)** — Get free AI with no credit card
- **[Troubleshooting](./TROUBLESHOOTING.md)** — Fix common issues
- **[Troubleshooting](../guides/TROUBLESHOOTING.md)** — Fix common issues
- **[Provider Reference](../reference/PROVIDER_REFERENCE.md)** — Full list of 226 providers

View File

@@ -153,7 +153,7 @@ You can see the details of the request by clicking [Monitoring/Logs](http://loca
- **[Auto-Combo Guide](./AUTO-COMBO-GUIDE.md)** — Let OmniRoute pick the best AI for you
- **[Providers Guide](./PROVIDERS-GUIDE.md)** — Connect more providers (free and paid)
- **[Free Tiers Guide](./FREE-TIERS-GUIDE.md)** — Get free AI with no credit card
- **[Troubleshooting](./TROUBLESHOOTING.md)** — Fix common issues
- **[Troubleshooting](../guides/TROUBLESHOOTING.md)** — Fix common issues
---
@@ -183,6 +183,6 @@ OmniRoute automatically skips failed providers and tries the next one. You don't
## Need Help?
- **[Troubleshooting](./TROUBLESHOOTING.md)** — Common issues and fixes
- **[Troubleshooting](../guides/TROUBLESHOOTING.md)** — Common issues and fixes
- **[Discord](https://discord.gg/U47eFqAXCn)** — Community support
- **[GitHub Issues](https://github.com/diegosouzapw/OmniRoute/issues)** — Report bugs

View File

@@ -1,498 +0,0 @@
---
title: "Troubleshooting"
version: 3.8.40
lastUpdated: 2026-06-28
---
# Troubleshooting
> **For Users**: Looking for quick fixes? See the [Quick Reference](#quick-reference) below.
🌐 **Languages:** 🇺🇸 [English](./TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](../i18n/pt-BR/docs/guides/TROUBLESHOOTING.md) | 🇪🇸 [Español](../i18n/es/docs/guides/TROUBLESHOOTING.md) | 🇫🇷 [Français](../i18n/fr/docs/guides/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](../i18n/it/docs/guides/TROUBLESHOOTING.md) | 🇷🇺 [Русский](../i18n/ru/docs/guides/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](../i18n/zh-CN/docs/guides/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](../i18n/de/docs/guides/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](../i18n/in/docs/guides/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](../i18n/th/docs/guides/TROUBLESHOOTING.md) | 🇺🇦 [Українська](../i18n/uk-UA/docs/guides/TROUBLESHOOTING.md) | 🇸🇦 [العربية](../i18n/ar/docs/guides/TROUBLESHOOTING.md) | 🇯🇵 [日本語](../i18n/ja/docs/guides/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](../i18n/vi/docs/guides/TROUBLESHOOTING.md) | 🇧🇬 [Български](../i18n/bg/docs/guides/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](../i18n/da/docs/guides/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](../i18n/fi/docs/guides/TROUBLESHOOTING.md) | 🇮🇱 [עברית](../i18n/he/docs/guides/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](../i18n/hu/docs/guides/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](../i18n/id/docs/guides/TROUBLESHOOTING.md) | 🇰🇷 [한국어](../i18n/ko/docs/guides/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](../i18n/ms/docs/guides/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](../i18n/nl/docs/guides/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](../i18n/no/docs/guides/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](../i18n/pt/docs/guides/TROUBLESHOOTING.md) | 🇷🇴 [Română](../i18n/ro/docs/guides/TROUBLESHOOTING.md) | 🇵🇱 [Polski](../i18n/pl/docs/guides/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](../i18n/sk/docs/guides/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](../i18n/sv/docs/guides/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](../i18n/phi/docs/guides/TROUBLESHOOTING.md) | 🇨🇿 [Čeština](../i18n/cs/docs/guides/TROUBLESHOOTING.md)
Common problems and solutions for OmniRoute.
---
## Quick Reference
**New to OmniRoute?** Start here — these solve 90% of problems:
| I see this | What it means | What to do |
| ----------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------- |
| "Can't connect" | OmniRoute isn't running | Run `omniroute` or `docker restart omniroute` |
| "Invalid API key" | Your key is wrong or expired | Re-copy the key from the provider's website |
| "Rate limit exceeded" | You're sending too many requests | Wait 1 minute, or use `model: "auto"` for automatic fallback |
| "Quota exceeded" | You've used up your free/paid quota | Connect more providers, or use free providers (Kiro, Pollinations) |
| "Slow responses" | Provider is busy or far away | Use `model: "auto/fast"` or connect a faster provider (Groq, Cerebras) |
| "Wrong provider used" | `auto` picked a different provider | That's normal! `auto` picks the best one. Force a specific provider with `model: "openai/gpt-4o"` |
| "502 Bad Gateway" | Provider is down | Wait and retry, or use `model: "auto"` to switch providers |
| "401 Unauthorized" | Your credentials are wrong | Check your API key or re-authenticate with OAuth |
| "429 Too Many Requests" | Rate limited | Wait 1 minute, or connect more providers |
**Still stuck?** See the [Quick Fixes](#quick-fixes) below, or ask on [Discord](https://discord.gg/U47eFqAXCn).
---
## npm install Warnings (ERESOLVE / peer / deprecated)
When you run `npm install -g omniroute`, you may see a wall of warnings like `npm warn ERESOLVE`, peer-dependency notices, and `deprecated` messages. **These are expected and harmless.** Your install succeeded if you see `added <N> packages` in the output.
The warnings come from stale peer-dependency ranges in third-party packages OmniRoute doesn't control:
1. **`marked-terminal` wants `marked >=1 <16`, found `marked@18`** — works fine in practice; the upstream peer range is just stale.
2. **`deprecated prebuild-install@7.1.3`** — the native-binary fetch helper. Only relevant later if a web-cookie provider reports a missing `tls-client-node` native binary (a separate issue, not caused by this warning).
**No action needed** — the warnings cannot be fully silenced without forking upstream packages.
---
## Quick Fixes
| Problem | Solution |
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
| No logs written to disk | Set `APP_LOG_TO_FILE=true` and verify call log capture is enabled |
| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
| Routing strategy not saving | Update to the latest v3.x release (Zod schema fix for settings persistence shipped in earlier versions) |
| Login crash / blank page | Check Node.js version — see [Node.js Compatibility](#nodejs-compatibility) below |
| `dlopen` / `slice is not valid mach-o file` (macOS) | Run `cd $(npm root -g)/omniroute/app && npm rebuild better-sqlite3 && omniroute` — see [macOS native module rebuild](#macos-native-module-rebuild) below |
| Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below |
---
## Node.js Compatibility
<a name="nodejs-compatibility"></a>
### Login page crashes or shows "Module self-registration" error
**Cause:** You are running a Node.js version outside OmniRoute's approved secure runtime floor. The most common case is running an older Node 22 or 24 patch level that falls below the patched security floor OmniRoute requires.
**Symptoms:**
- Login page shows a blank screen or a server error
- Console shows `Error: Module did not self-register` or similar native binding errors
- The login page shows an **orange warning banner** with your Node version if the runtime is outside the supported secure policy
**Fix:**
1. Install a supported Node.js LTS release (recommended: Node.js 24.x):
```bash
nvm install 24
nvm use 24
```
2. Verify your version: `node --version` should show `v24.0.0` or newer on the 24.x LTS line
3. Reinstall OmniRoute: `npm install -g omniroute`
4. Restart: `omniroute`
> **Supported secure versions:** `>=22.22.2 <23` or `>=24.0.0 <27`. Node.js 24.x LTS (Krypton) and Node.js 26 are fully supported.
### macOS: `dlopen` / "slice is not valid mach-o file"
<a name="macos-native-module-rebuild"></a>
**Cause:** After a global `npm install -g omniroute`, the `better-sqlite3` native binary inside the package may have been compiled for a different architecture or Node.js ABI than what is running locally. This is common on macOS (both Apple Silicon and Intel) when the pre-built binary does not match your environment.
**Symptoms:**
- Server fails immediately on startup with a `dlopen` error
- Error contains `slice is not valid mach-o file`
- Full example:
```
dlopen(/Users/<user>/.nvm/versions/node/v24.14.1/lib/node_modules/omniroute/app/node_modules/better-sqlite3/build/Release/better_sqlite3.node, 0x0001): tried: '...' (slice is not valid mach-o file)
```
**Fix — rebuild for your local environment (no Node.js downgrade required):**
```bash
cd $(npm root -g)/omniroute/app
npm rebuild better-sqlite3
omniroute
```
> **Note:** This recompiles the native binding against your local Node.js version and CPU architecture, resolving the binary mismatch. The officially supported runtime range is **`>=22.22.2 <23` or `>=24.0.0 <27`** (`SUPPORTED_NODE_RANGE` in `src/shared/utils/nodeRuntimeSupport.ts`, aligned with the `package.json` `engines` field). Node.js 24.x LTS (Krypton) and Node.js 26 are fully supported with `better-sqlite3` v12.x.
---
## Proxy Issues
<a name="proxy-issues"></a>
### Provider validation shows "fetch failed"
**Cause:** The API key validation endpoint (`POST /api/providers/validate`) was previously bypassing proxy configuration, causing failures in environments that require proxy routing.
**Fix (v3.5.5+):** This is now fixed. Provider validation routes through `runWithProxyContext`, honoring provider-level and global proxy settings automatically.
### Token health check fails with "fetch failed"
**Cause:** Background OAuth token refresh was not resolving proxy configuration per connection.
**Fix (v3.5.5+):** The token health check scheduler now resolves proxy config per connection before attempting refresh. Update to v3.5.5+.
### SOCKS5 proxy returns "invalid onRequestStart method"
**Cause:** On Node.js 22, the undici@8 dispatcher is incompatible with Node's built-in `fetch()` implementation.
**Fix (v3.5.5+):** OmniRoute now uses undici's own `fetch()` function when a proxy dispatcher is active, ensuring consistent behavior. Update to v3.5.5+.
---
## Provider Issues
### "Language model did not provide messages"
**Cause:** Provider quota exhausted.
**Fix:**
1. Check dashboard quota tracker
2. Use a combo with fallback tiers
3. Switch to cheaper/free tier
### Rate Limiting
**Cause:** Subscription quota exhausted.
**Fix:**
- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/qwen3.8-max-preview`
- Use GLM/MiniMax as cheap backup
### OAuth Token Expired
OmniRoute auto-refreshes tokens. If issues persist:
1. Dashboard → Provider → Reconnect
2. Delete and re-add the provider connection
### Kiro multi-account: second account invalidates the first
**Cause:** Kiro's backend enforces a single active session per OIDC client registration.
When two accounts share the same registered client (connections imported before v3.8.0),
refreshing one account's token invalidates the other's refresh token.
**Fix (v3.8.0+):** Re-import affected connections.
Starting with v3.8.0, every new Kiro connection created via **Import Token**,
**Google/GitHub social login**, or **Auto-Import** automatically registers its own
dedicated OIDC client. The connection is therefore fully isolated and refreshing one
account has no effect on any other account.
Connections that were imported _before_ v3.8.0 do not carry a per-connection client
registration. Those connections continue to use the shared social-auth refresh endpoint.
To gain isolation, delete the old connection from Dashboard → Providers and re-add it
via any of the three import flows.
For full details and step-by-step instructions for adding two Kiro accounts side by side,
see [`docs/guides/KIRO_SETUP.md`](../guides/KIRO_SETUP.md).
---
## Cloud Issues
### Cloud Sync Errors
1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
### Cloud `stream=false` Returns 500
**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
**Cause:** Upstream returns SSE payload while client expects JSON.
**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
### Cloud Says Connected but "Invalid API key"
1. Create a fresh key from local dashboard (`/api/keys`)
2. Run cloud sync: Enable Cloud → Sync Now
3. Old/non-synced keys can still return `401` on cloud
---
## Docker Issues
### CLI Tool Shows Not Installed
1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
2. For portable mode: use image target `runner-cli` (bundled CLIs)
3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
### Quick Runtime Validation
```bash
curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
```
---
## Cost Issues
### High Costs
1. Check usage stats in Dashboard → Usage
2. Switch primary model to GLM/MiniMax
3. Use free tier (Qoder, Kiro) for non-critical tasks
4. Set cost budgets per API key: Dashboard → API Keys → Budget
---
## Debugging
### Enable Log Files
Set `APP_LOG_TO_FILE=true` in your `.env` file. Application logs are written under `logs/`.
Request artifacts are stored under `${DATA_DIR}/call_logs/` when the call log pipeline is
enabled in settings.
When pipeline capture is enabled, set `CALL_LOG_PIPELINE_CAPTURE_STREAM_CHUNKS=false` to omit
stream chunk payloads, or tune `CALL_LOG_PIPELINE_MAX_SIZE_KB` to change the artifact cap in KB.
### Check Provider Health
```bash
# Health dashboard
http://localhost:20128/dashboard/health
# API health check
curl http://localhost:20128/api/monitoring/health
```
### Runtime Storage
- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/call_logs/`
- Application logs: `<repo>/logs/...` (when `APP_LOG_TO_FILE=true`)
- Call log artifacts: `${DATA_DIR}/call_logs/YYYY-MM-DD/...` when the call log pipeline is enabled
The Request Logs page's **Clean history** action clears `call_logs`, legacy
`request_detail_logs`, and the local `${DATA_DIR}/call_logs/` artifact directory.
---
## Circuit Breaker Issues
### Provider stuck in OPEN state
When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
**Fix:**
1. Go to **Dashboard → Settings → Resilience**
2. Check the circuit breaker card for the affected provider
3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
4. Verify the provider is actually available before resetting
### Provider keeps tripping the circuit breaker
If a provider repeatedly enters OPEN state:
1. Check **Dashboard → Health → Provider Health** for the failure pattern
2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
3. Check if the provider has changed API limits or requires re-authentication
4. Review latency telemetry — high latency may cause timeout-based failures
---
## Audio Transcription Issues
### "Unsupported model" error
- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
- Verify the provider is connected in **Dashboard → Providers**
### Transcription returns empty or fails
- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
- Verify file size is within provider limits (typically < 25MB)
- Check provider API key validity in the provider card
---
## Translator Debugging
Use **Dashboard → Translator** to debug format translation issues:
| Mode | When to Use |
| ---------------- | -------------------------------------------------------------------------------------------- |
| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
### Common format issues
- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
- **SDK returns raw string instead of object** — Resolved in v1.x; response sanitizer strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures. If you still see this on v3.x+, please file an issue.
- **GLM/ERNIE rejects `system` role** — Resolved in v1.x; role normalizer automatically merges system messages into user messages for incompatible models. If you still see this on v3.x+, please file an issue.
- **`developer` role not recognized** — Resolved in v1.x; automatically converted to `system` for non-OpenAI providers. If you still see this on v3.x+, please file an issue.
- **`json_schema` not working with Gemini** — Resolved in v1.x; `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`. If you still see this on v3.x+, please file an issue.
---
## Resilience Settings
### Auto rate-limit not triggering
- Auto rate-limit only applies to API key providers (not OAuth/subscription)
- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
- Check if the provider returns `429` status codes or `Retry-After` headers
### Tuning exponential backoff
Provider profiles support these settings:
- **Base delay** — Initial wait time after first failure (default: 1s)
- **Max delay** — Maximum wait time cap (default: 30s)
- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
### Anti-thundering herd
When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
---
## Optional RAG / LLM failure taxonomy (16 problems)
Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
- retrieval drift and broken context boundaries
- empty or stale indexes and vector stores
- embedding versus semantic mismatch
- prompt assembly and context window issues
- logic collapse and overconfident answers
- long chain and agent coordination failures
- multi agent memory and role drift
- deployment and bootstrap ordering problems
The idea is simple:
1. When you investigate a bad response, capture:
- user task and request
- route or provider combo in OmniRoute
- any RAG context used downstream (retrieved documents, tool calls, etc)
2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
Full text and concrete recipes live here (MIT license, text only):
[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
---
## v3.8.0 Known Issues
Issues specific to the v3.8.0 release and their current workarounds. If a fix lands in a later patch, the entry will be updated or removed.
### Devin CLI auth failures
**Symptoms:**
- "Devin CLI not found" or "auth failed" when invoking Devin-backed tools
- CLI runtime check reports `installed=false`
**Causes:**
- `CLI_DEVIN_BIN` points to a path that does not exist
- Devin CLI is not installed on the host
**Fix:**
1. Install the Devin CLI for your platform
2. Set `CLI_DEVIN_BIN=/usr/local/bin/devin` (or the real path) in `.env`
3. Restart OmniRoute and re-test from **Dashboard → CLI Tools**
### Model cooldown stuck (manual reset)
**Symptoms:**
- A model stays listed in cooldown even after the expiration time has passed
- Requests still skip the model in combo routing despite the timestamp being in the past
**Manual reset:**
- **Dashboard:** **Settings → Model Cooldowns** → click **Re-enable** on the affected card
- **API:** `DELETE /api/resilience/model-cooldowns` with management auth headers
### Command Code provider connection fails with 403
**Symptoms:**
- 403 when testing the Command Code provider connection
- The provider card shows "unauthorized" after a fresh add
**Cause:** The OAuth flow did not complete (callback not received or token not persisted).
**Fix:**
- Run `omniroute providers` from the CLI to re-trigger the OAuth flow, or
- Re-run OAuth from **Dashboard → Providers → Command Code → Reconnect**
### ModelScope returns aggressive 429 cooldowns
**Symptoms:**
- Very short or immediate cooldowns on ModelScope after a small burst of requests
- Combo routing skips ModelScope earlier than expected
**Cause:** ModelScope emits provider-specific `Retry-After` headers. v3.8.0 ships dedicated handling for those headers, so older versions misread them as generic rate-limit hints.
**Fix:**
- Ensure you are on v3.8.0 or later
- Verify the `useUpstream429BreakerHints` toggle is enabled under **Settings → Resilience**
### OMNIROUTE_WS_BRIDGE_SECRET missing in production
**Symptoms:**
- 401 on every Codex/Responses WebSocket bridge request when running on a remote production host
- WebSocket bridge handshake closes immediately after connect
**Cause:** The `OMNIROUTE_WS_BRIDGE_SECRET` env var is missing from the production environment.
**Fix:**
1. Generate a random secret: `openssl rand -hex 32`
2. Set `OMNIROUTE_WS_BRIDGE_SECRET=<random-secret>` in the production server env (and any client that talks to the bridge)
3. Restart OmniRoute
### Responses API: background mode degraded to synchronous
**Symptoms:**
- Warning logged: `background mode degraded to synchronous`
- A `background: true` request returns a normal synchronous response instead of a background job handle
**Cause:** v3.8.0 intentionally degrades `background: true` on the Responses API to synchronous execution while emitting a warning. Full async background execution is a future deliverable.
**Fix:**
- Adjust the client to call without `background`, or
- Wait for a later release that ships full async background mode (track the changelog)
---
## Still Stuck?
- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **Architecture**: See [`docs/architecture/ARCHITECTURE.md`](../architecture/ARCHITECTURE.md) for internal details
- **API Reference**: See [`docs/reference/API_REFERENCE.md`](../reference/API_REFERENCE.md) for all endpoints
- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
- **Translator**: Use **Dashboard → Translator** to debug format issues

View File

@@ -336,6 +336,57 @@ Endpoint tunnel panels (Cloudflare, Tailscale, ngrok) can be shown or hidden fro
Multi-platform manifest: `linux/amd64` + `linux/arm64` native (Apple Silicon, AWS Graviton, Raspberry Pi). Docker selects the matching architecture automatically; pass `--platform linux/amd64` if you need to force AMD64 emulation on ARM hosts.
### Release Channels
OmniRoute publishes separate Docker channels for stable releases, active release-branch testing, and development builds.
| Channel | Source | Mutability | Recommended use |
| --- | --- | --- | --- |
| `:<version>` / `:<version>-web` | Signed/versioned release | Immutable | Production deployments that pin an exact release |
| `:latest` / `:latest-web` | Highest stable release | Mutable stable pointer | Production deployments that intentionally follow stable releases |
| `:next` / `:next-web` | Current default `release/v*` branch | Mutable pre-release pointer | Testing fixes that have landed on the active release branch but are not yet in a stable release |
| `:main` / `:main-web` | `main` branch | Mutable development pointer | Development and integration testing only |
#### Using the pre-release channel
The `next` channel is rebuilt on every push to the current default `release/v*` branch and is published for both AMD64 and ARM64. Older maintenance branches cannot overwrite it. The channel provides a pullable image for fixes that have merged into the active release branch before the next stable tag is cut.
```bash
docker pull diegosouzapw/omniroute:next
docker pull diegosouzapw/omniroute:next-web
```
For Docker Compose, override the image tag used by the selected profile, then pull and recreate the service:
```yaml
services:
omniroute:
image: diegosouzapw/omniroute:next
```
```bash
docker compose pull
docker compose up -d
```
#### Safety and rollback
`next` is a floating pre-release channel. It may change on any push to the active release branch and is **not supported for production use**. Pin the image digest while evaluating a specific build:
```bash
docker pull diegosouzapw/omniroute:next
docker image inspect diegosouzapw/omniroute:next --format '{{index .RepoDigests 0}}'
```
Before testing, back up the OmniRoute data volume or bind-mounted data directory. To roll back, restore the previously used stable version or digest and recreate the container:
```bash
docker pull diegosouzapw/omniroute:<stable-version>
docker compose up -d
```
A release-branch build can never move `latest`; only an eligible stable semantic version may promote the stable pointer. The `next` images retain the release image inspection and blocking CRITICAL-vulnerability gate.
## Important Notes
- **SQLite WAL Mode:** `docker stop` should be allowed to finish so OmniRoute can checkpoint the latest changes back into `storage.sqlite`. The bundled Compose files already set a 40s stop grace period. If you run the image directly, keep `--stop-timeout 40`.

View File

@@ -1,58 +0,0 @@
---
title: "Docker Release Channels"
version: 3.8.50
lastUpdated: 2026-08-06
---
# Docker Release Channels
OmniRoute publishes separate Docker channels for stable releases, active release-branch testing, and development builds.
## Channel summary
| Channel | Source | Mutability | Recommended use |
| --- | --- | --- | --- |
| `:<version>` / `:<version>-web` | Signed/versioned release | Immutable | Production deployments that pin an exact release |
| `:latest` / `:latest-web` | Highest stable release | Mutable stable pointer | Production deployments that intentionally follow stable releases |
| `:next` / `:next-web` | Current default `release/v*` branch | Mutable pre-release pointer | Testing fixes that have landed on the active release branch but are not yet in a stable release |
| `:main` / `:main-web` | `main` branch | Mutable development pointer | Development and integration testing only |
## Using the pre-release channel
The `next` channel is rebuilt on every push to the current default `release/v*` branch and is published for both AMD64 and ARM64. Older maintenance branches cannot overwrite it. The channel provides a pullable image for fixes that have merged into the active release branch before the next stable tag is cut.
```bash
docker pull diegosouzapw/omniroute:next
docker pull diegosouzapw/omniroute:next-web
```
For Docker Compose, override the image tag used by the selected profile, then pull and recreate the service:
```yaml
services:
omniroute:
image: diegosouzapw/omniroute:next
```
```bash
docker compose pull
docker compose up -d
```
## Safety and rollback
`next` is a floating pre-release channel. It may change on any push to the active release branch and is **not supported for production use**. Pin the image digest while evaluating a specific build:
```bash
docker pull diegosouzapw/omniroute:next
docker image inspect diegosouzapw/omniroute:next --format '{{index .RepoDigests 0}}'
```
Before testing, back up the OmniRoute data volume or bind-mounted data directory. To roll back, restore the previously used stable version or digest and recreate the container:
```bash
docker pull diegosouzapw/omniroute:<stable-version>
docker compose up -d
```
A release-branch build can never move `latest`; only an eligible stable semantic version may promote the stable pointer. The `next` images retain the release image inspection and blocking CRITICAL-vulnerability gate.

View File

@@ -38,6 +38,19 @@ Common problems and solutions for OmniRoute.
---
## npm install Warnings (ERESOLVE / peer / deprecated)
When you run `npm install -g omniroute`, you may see a wall of warnings like `npm warn ERESOLVE`, peer-dependency notices, and `deprecated` messages. **These are expected and harmless.** Your install succeeded if you see `added <N> packages` in the output.
The warnings come from stale peer-dependency ranges in third-party packages OmniRoute doesn't control:
1. **`marked-terminal` wants `marked >=1 <16`, found `marked@18`** — works fine in practice; the upstream peer range is just stale.
2. **`deprecated prebuild-install@7.1.3`** — the native-binary fetch helper. Only relevant later if a web-cookie provider reports a missing `tls-client-node` native binary (a separate issue, not caused by this warning).
**No action needed** — the warnings cannot be fully silenced without forking upstream packages.
---
## Quick Fixes
| Problem | Solution |

View File

@@ -1,498 +0,0 @@
---
title: "Rozwiązywanie problemów"
version: 3.8.40
lastUpdated: 2026-06-28
---
# Rozwiązywanie problemów
> **Dla użytkowników**: Szukasz szybkich poprawek? Zobacz [Szybki przewodnik](#quick-reference) poniżej.
🌐 **Languages:** 🇺🇸 [English](./TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](../i18n/pt-BR/docs/guides/TROUBLESHOOTING.md) | 🇪🇸 [Español](../i18n/es/docs/guides/TROUBLESHOOTING.md) | 🇫🇷 [Français](../i18n/fr/docs/guides/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](../i18n/it/docs/guides/TROUBLESHOOTING.md) | 🇷🇺 [Русский](../i18n/ru/docs/guides/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](../i18n/zh-CN/docs/guides/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](../i18n/de/docs/guides/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](../i18n/in/docs/guides/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](../i18n/th/docs/guides/TROUBLESHOOTING.md) | 🇺🇦 [Українська](../i18n/uk-UA/docs/guides/TROUBLESHOOTING.md) | 🇸🇦 [العربية](../i18n/ar/docs/guides/TROUBLESHOOTING.md) | 🇯🇵 [日本語](../i18n/ja/docs/guides/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](../i18n/vi/docs/guides/TROUBLESHOOTING.md) | 🇧🇬 [Български](../i18n/bg/docs/guides/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](../i18n/da/docs/guides/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](../i18n/fi/docs/guides/TROUBLESHOOTING.md) | 🇮🇱 [עברית](../i18n/he/docs/guides/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](../i18n/hu/docs/guides/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](../i18n/id/docs/guides/TROUBLESHOOTING.md) | 🇰🇷 [한국어](../i18n/ko/docs/guides/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](../i18n/ms/docs/guides/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](../i18n/nl/docs/guides/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](../i18n/no/docs/guides/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](../i18n/pt/docs/guides/TROUBLESHOOTING.md) | 🇷🇴 [Română](../i18n/ro/docs/guides/TROUBLESHOOTING.md) | 🇵🇱 [Polski](../i18n/pl/docs/guides/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](../i18n/sk/docs/guides/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](../i18n/sv/docs/guides/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](../i18n/phi/docs/guides/TROUBLESHOOTING.md) | 🇨🇿 [Čeština](../i18n/cs/docs/guides/TROUBLESHOOTING.md)
Typowe problemy i rozwiązania dla OmniRoute.
---
## Szybki przewodnik
**Nowy w OmniRoute?** Zacznij tutaj — te wskazówki rozwiązują 90% problemów:
| Widzę to | Co to oznacza | Co zrobić |
| ----------------------- | ---------------------------------- | ------------------------------------------------------------------------------------ |
| "Can't connect" | OmniRoute nie działa | Uruchom `omniroute` lub `docker restart omniroute` |
| "Invalid API key" | Klucz jest błędny lub wygasł | Skopiuj ponownie klucz ze strony providera |
| "Rate limit exceeded" | Wysyłasz zbyt wiele żądań | Poczekaj 1 minutę albo użyj `model: "auto"` do automatycznego fallbacku |
| "Quota exceeded" | Wykorzystałeś darmowy/płatny limit | Podłącz więcej providerów albo użyj darmowych (Kiro, Pollinations) |
| "Slow responses" | Provider jest obciążony lub daleko | Użyj `model: "auto/fast"` albo podłącz szybszego providera (Groq, Cerebras) |
| "Wrong provider used" | `auto` wybrał innego providera | To normalne! `auto` wybiera najlepszego. Wymuś konkretnego: `model: "openai/gpt-4o"` |
| "502 Bad Gateway" | Provider nie działa | Poczekaj i spróbuj ponownie albo użyj `model: "auto"`, aby przełączyć providera |
| "401 Unauthorized" | Błędne dane uwierzytelniające | Sprawdź klucz API albo ponownie uwierzytelnij się przez OAuth |
| "429 Too Many Requests" | Limit zapytań | Poczekaj 1 minutę albo podłącz więcej providerów |
**Nadal utknąłeś?** Zobacz [Szybkie poprawki](#quick-fixes) poniżej albo zapytaj na [Discordzie](https://discord.gg/U47eFqAXCn).
---
## Ostrzeżenia npm install (ERESOLVE / peer / deprecated)
Po `npm install -g omniroute` możesz zobaczyć lawinę ostrzeżeń typu `npm warn ERESOLVE`, komunikaty o peer-dependency oraz `deprecated`. **Są one oczekiwane i nieszkodliwe.** Instalacja się powiodła, jeśli w wyniku widać `added <N> packages`.
Ostrzeżenia pochodzą z przestarzałych zakresów peer-dependency w pakietach firm trzecich, których OmniRoute nie kontroluje:
1. **`marked-terminal` chce `marked >=1 <16`, znaleziono `marked@18`** — w praktyce działa poprawnie; zakres peer po stronie upstream jest po prostu nieaktualny.
2. **`deprecated prebuild-install@7.1.3`** — helper do pobierania natywnych binarek. Istotny dopiero później, jeśli provider web-cookie zgłosi brak natywnej binarki `tls-client-node` (osobny problem, nie spowodowany tym ostrzeżeniem).
**Nie trzeba nic robić** — ostrzeżeń nie da się w pełni wyciszyć bez forka pakietów upstream.
---
## Szybkie poprawki
| Problem | Rozwiązanie |
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Pierwsze logowanie nie działa | Ustaw `INITIAL_PASSWORD` w `.env` (brak wbudowanego domyślnego hasła) |
| Dashboard otwiera się na złym porcie | Ustaw `PORT=20128` i `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
| Brak logów na dysku | Ustaw `APP_LOG_TO_FILE=true` i upewnij się, że przechwytywanie call log jest włączone |
| EACCES: permission denied | Ustaw `DATA_DIR=/path/to/writable/dir`, aby nadpisać `~/.omniroute` |
| Strategia routingu się nie zapisuje | Zaktualizuj do najnowszego wydania v3.x (poprawka schematu Zod dla persystencji ustawień weszła we wcześniejszych wersjach) |
| Crash logowania / pusta strona | Sprawdź wersję Node.js — zobacz [Zgodność z Node.js](#nodejs-compatibility) poniżej |
| `dlopen` / `slice is not valid mach-o file` (macOS) | Uruchom `cd $(npm root -g)/omniroute/app && npm rebuild better-sqlite3 && omniroute` — zobacz [przebudowa modułu natywnego na macOS](#macos-native-module-rebuild) poniżej |
| Proxy "fetch failed" | Upewnij się, że konfiguracja proxy jest ustawiona na właściwym poziomie — zobacz [Problemy z proxy](#proxy-issues) poniżej |
---
## Zgodność z Node.js
<a name="nodejs-compatibility"></a>
### Strona logowania się wykrzacza lub pokazuje błąd "Module self-registration"
**Przyczyna:** Uruchamiasz wersję Node.js poniżej zatwierdzonego bezpiecznego poziomu runtime OmniRoute. Najczęstszy przypadek to starszy patch Node 22 lub 24 poniżej wymaganego przez OmniRoute poziomu bezpieczeństwa.
**Objawy:**
- Strona logowania pokazuje pusty ekran lub błąd serwera
- Konsola pokazuje `Error: Module did not self-register` lub podobne błędy natywnych bindingów
- Strona logowania pokazuje **pomarańczowy baner ostrzegawczy** z Twoją wersją Node, jeśli runtime jest poza wspieraną bezpieczną polityką
**Naprawa:**
1. Zainstaluj wspierane wydanie Node.js LTS (zalecane: Node.js 24.x):
```bash
nvm install 24
nvm use 24
```
2. Sprawdź wersję: `node --version` powinno pokazać `v24.0.0` lub nowsze w linii LTS 24.x
3. Zainstaluj ponownie OmniRoute: `npm install -g omniroute`
4. Uruchom ponownie: `omniroute`
> **Wspierane bezpieczne wersje:** `>=22.22.2 <23` lub `>=24.0.0 <27`. Node.js 24.x LTS (Krypton) oraz Node.js 26 są w pełni wspierane.
### macOS: `dlopen` / "slice is not valid mach-o file"
<a name="macos-native-module-rebuild"></a>
**Przyczyna:** Po globalnym `npm install -g omniroute` natywna binarka `better-sqlite3` w pakiecie mogła zostać skompilowana pod inną architekturę lub ABI Node.js niż ta, która działa lokalnie. To częste na macOS (Apple Silicon i Intel), gdy prebuilt nie pasuje do środowiska.
**Objawy:**
- Serwer pada natychmiast przy starcie z błędem `dlopen`
- Błąd zawiera `slice is not valid mach-o file`
- Pełny przykład:
```
dlopen(/Users/<user>/.nvm/versions/node/v24.14.1/lib/node_modules/omniroute/app/node_modules/better-sqlite3/build/Release/better_sqlite3.node, 0x0001): tried: '...' (slice is not valid mach-o file)
```
**Naprawa — przebuduj pod lokalne środowisko (bez downgrade Node.js):**
```bash
cd $(npm root -g)/omniroute/app
npm rebuild better-sqlite3
omniroute
```
> **Uwaga:** To rekompiluje natywny binding względem lokalnej wersji Node.js i architektury CPU, usuwając niedopasowanie binarki. Oficjalnie wspierany zakres runtime to **`>=22.22.2 <23` lub `>=24.0.0 <27`** (`SUPPORTED_NODE_RANGE` w `src/shared/utils/nodeRuntimeSupport.ts`, zgodny z polem `engines` w `package.json`). Node.js 24.x LTS (Krypton) oraz Node.js 26 są w pełni wspierane z `better-sqlite3` v12.x.
---
## Problemy z proxy
<a name="proxy-issues"></a>
### Walidacja providera pokazuje "fetch failed"
**Przyczyna:** Endpoint walidacji klucza API (`POST /api/providers/validate`) wcześniej omijał konfigurację proxy, co powodowało błędy w środowiskach wymagających routingu przez proxy.
**Naprawa (v3.5.5+):** To już naprawione. Walidacja providera idzie przez `runWithProxyContext` i automatycznie respektuje ustawienia proxy na poziomie providera oraz globalne.
### Token health check kończy się "fetch failed"
**Przyczyna:** Tło odświeżania tokenów OAuth nie rozwiązywało konfiguracji proxy per połączenie.
**Naprawa (v3.5.5+):** Scheduler token health check rozwiązuje teraz config proxy per połączenie przed odświeżeniem. Zaktualizuj do v3.5.5+.
### Proxy SOCKS5 zwraca "invalid onRequestStart method"
**Przyczyna:** Na Node.js 22 dispatcher undici@8 jest niekompatybilny z wbudowaną implementacją `fetch()` w Node.
**Naprawa (v3.5.5+):** OmniRoute używa teraz własnej funkcji `fetch()` z undici, gdy aktywny jest dispatcher proxy, co zapewnia spójne zachowanie. Zaktualizuj do v3.5.5+.
---
## Problemy z providerami
### "Language model did not provide messages"
**Przyczyna:** Wyczerpany limit (quota) providera.
**Naprawa:**
1. Sprawdź tracker limitu w dashboardzie
2. Użyj combo z poziomami fallback
3. Przełącz się na tańszy/darmowy tier
### Rate limiting
**Przyczyna:** Wyczerpany limit subskrypcji.
**Naprawa:**
- Dodaj fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/qwen3.8-max-preview`
- Użyj GLM/MiniMax jako taniego zapasowego
### Wygasły token OAuth
OmniRoute automatycznie odświeża tokeny. Jeśli problemy trwają:
1. Dashboard → Provider → Reconnect
2. Usuń i dodaj ponownie połączenie providera
### Kiro multi-account: drugie konto unieważnia pierwsze
**Przyczyna:** Backend Kiro wymusza jedną aktywną sesję na rejestrację klienta OIDC.
Gdy dwa konta współdzielą tego samego zarejestrowanego klienta (połączenia zaimportowane przed v3.8.0),
odświeżenie tokenu jednego konta unieważnia refresh token drugiego.
**Naprawa (v3.8.0+):** Zaimportuj ponownie dotknięte połączenia.
Od v3.8.0 każde nowe połączenie Kiro utworzone przez **Import Token**,
**Google/GitHub social login** lub **Auto-Import** automatycznie rejestruje własnego
dedykowanego klienta OIDC. Połączenie jest więc w pełni izolowane i odświeżenie jednego
konta nie wpływa na żadne inne.
Połączenia zaimportowane _przed_ v3.8.0 nie niosą rejestracji klienta per połączenie.
Te połączenia nadal używają współdzielonego endpointu odświeżania social-auth.
Aby uzyskać izolację, usuń stare połączenie z Dashboard → Providers i dodaj je ponownie
przez dowolny z trzech przepływów importu.
Pełne szczegóły i instrukcja krok po kroku dodawania dwóch kont Kiro obok siebie:
zobacz [`docs/guides/KIRO_SETUP.md`](../guides/KIRO_SETUP.md).
---
## Problemy z chmurą
### Błędy synchronizacji chmury
1. Sprawdź, czy `BASE_URL` wskazuje na działającą instancję (np. `http://localhost:20128`)
2. Sprawdź, czy `CLOUD_URL` wskazuje na endpoint chmury (np. `https://omniroute.dev`)
3. Utrzymuj wartości `NEXT_PUBLIC_*` zgodne z wartościami po stronie serwera
### Cloud `stream=false` zwraca 500
**Objaw:** `Unexpected token 'd'...` na endpoincie chmury przy wywołaniach bez streamingu.
**Przyczyna:** Upstream zwraca payload SSE, a klient oczekuje JSON.
**Obejście:** Użyj `stream=true` przy bezpośrednich wywołaniach cloud. Lokalny runtime ma fallback SSE→JSON.
### Cloud pokazuje Connected, ale "Invalid API key"
1. Utwórz świeży klucz z lokalnego dashboardu (`/api/keys`)
2. Uruchom synchronizację chmury: Enable Cloud → Sync Now
3. Stare/niesynchronizowane klucze mogą nadal zwracać `401` w chmurze
---
## Problemy z Dockerem
### Narzędzie CLI pokazuje Not Installed
1. Sprawdź pola runtime: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
2. Dla trybu portable: użyj targetu obrazu `runner-cli` (dołączone CLI)
3. Dla trybu host mount: ustaw `CLI_EXTRA_PATHS` i zamontuj katalog bin hosta jako tylko do odczytu
4. Jeśli `installed=true` i `runnable=false`: binarka znaleziona, ale healthcheck się nie powiódł
### Szybka walidacja runtime
```bash
curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
```
---
## Problemy z kosztami
### Wysokie koszty
1. Sprawdź statystyki użycia w Dashboard → Usage
2. Przełącz model główny na GLM/MiniMax
3. Używaj darmowego tieru (Qoder, Kiro) do mniej krytycznych zadań
4. Ustaw budżety kosztów per klucz API: Dashboard → API Keys → Budget
---
## Debugowanie
### Włącz pliki logów
Ustaw `APP_LOG_TO_FILE=true` w pliku `.env`. Logi aplikacji trafiają do `logs/`.
Artefakty żądań są przechowywane w `${DATA_DIR}/call_logs/`, gdy pipeline call log jest
włączony w ustawieniach.
Gdy przechwytywanie pipeline jest włączone, ustaw `CALL_LOG_PIPELINE_CAPTURE_STREAM_CHUNKS=false`, aby pominąć
payloady chunków streamu, albo dostrój `CALL_LOG_PIPELINE_MAX_SIZE_KB`, aby zmienić limit artefaktu w KB.
### Sprawdź zdrowie providerów
```bash
# Health dashboard
http://localhost:20128/dashboard/health
# API health check
curl http://localhost:20128/api/monitoring/health
```
### Przechowywanie w runtime
- Stan główny: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
- Użycie: tabele SQLite w `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + opcjonalnie `${DATA_DIR}/call_logs/`
- Logi aplikacji: `<repo>/logs/...` (gdy `APP_LOG_TO_FILE=true`)
- Artefakty call log: `${DATA_DIR}/call_logs/YYYY-MM-DD/...` gdy pipeline call log jest włączony
Akcja **Clean history** na stronie Request Logs czyści `call_logs`, legacy
`request_detail_logs` oraz lokalny katalog artefaktów `${DATA_DIR}/call_logs/`.
---
## Problemy z circuit breakerem
### Provider utknął w stanie OPEN
Gdy circuit breaker providera jest OPEN, żądania są blokowane do wygaśnięcia cooldownu.
**Naprawa:**
1. Przejdź do **Dashboard → Settings → Resilience**
2. Sprawdź kartę circuit breakera dla dotkniętego providera
3. Kliknij **Reset All**, aby wyczyścić wszystkie breakery, albo poczekaj na wygaśnięcie cooldownu
4. Upewnij się, że provider jest faktycznie dostępny przed resetem
### Provider wciąż wyzwala circuit breaker
Jeśli provider wielokrotnie wchodzi w stan OPEN:
1. Sprawdź **Dashboard → Health → Provider Health** pod kątem wzorca awarii
2. Przejdź do **Settings → Resilience → Provider Profiles** i zwiększ próg awarii
3. Sprawdź, czy provider zmienił limity API lub wymaga ponownego uwierzytelnienia
4. Przejrzyj telemetrię opóźnień — wysoka latencja może powodować awarie oparte na timeoutach
---
## Problemy z transkrypcją audio
### Błąd "Unsupported model"
- Upewnij się, że używasz właściwego prefiksu: `deepgram/nova-3` lub `assemblyai/best`
- Sprawdź, czy provider jest podłączony w **Dashboard → Providers**
### Transkrypcja zwraca pusto lub się nie udaje
- Sprawdź wspierane formaty audio: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
- Upewnij się, że rozmiar pliku mieści się w limitach providera (zazwyczaj < 25MB)
- Sprawdź ważność klucza API na karcie providera
---
## Debugowanie translatora
Użyj **Dashboard → Translator**, aby debugować problemy z tłumaczeniem formatów:
| Tryb | Kiedy używać |
| ---------------- | ---------------------------------------------------------------------------------------------- |
| **Playground** | Porównaj formaty wejścia/wyjścia obok siebie — wklej padające żądanie, by zobaczyć tłumaczenie |
| **Chat Tester** | Wysyłaj żywe wiadomości i przeglądaj pełny payload request/response wraz z nagłówkami |
| **Test Bench** | Uruchamiaj testy wsadowe na kombinacjach formatów, by znaleźć zepsute tłumaczenia |
| **Live Monitor** | Obserwuj przepływ żądań w czasie rzeczywistym, by wyłapać przerywane problemy z tłumaczeniem |
### Typowe problemy z formatami
- **Brak tagów thinking** — Sprawdź, czy docelowy provider wspiera thinking i ustawienie thinking budget
- **Znikające tool calls** — Niektóre tłumaczenia formatów mogą usuwać nieobsługiwane pola; sprawdź w trybie Playground
- **Brak system prompt** — Claude i Gemini obsługują system prompts inaczej; sprawdź wynik tłumaczenia
- **SDK zwraca surowy string zamiast obiektu** — Naprawione w v1.x; sanitizer odpowiedzi usuwa niestandardowe pola (`x_groq`, `usage_breakdown` itd.), które powodują błędy walidacji Pydantic w OpenAI SDK. Jeśli nadal to widzisz na v3.x+, zgłoś issue.
- **GLM/ERNIE odrzuca rolę `system`** — Naprawione w v1.x; normalizer ról automatycznie scala wiadomości system w user dla niekompatybilnych modeli. Jeśli nadal to widzisz na v3.x+, zgłoś issue.
- **Rola `developer` nierozpoznana** — Naprawione w v1.x; automatycznie konwertowana na `system` dla providerów spoza OpenAI. Jeśli nadal to widzisz na v3.x+, zgłoś issue.
- **`json_schema` nie działa z Gemini** — Naprawione w v1.x; `response_format` jest teraz konwertowany na `responseMimeType` + `responseSchema` Gemini. Jeśli nadal to widzisz na v3.x+, zgłoś issue.
---
## Ustawienia odporności (Resilience)
### Auto rate-limit się nie uruchamia
- Auto rate-limit dotyczy tylko providerów z kluczem API (nie OAuth/subskrypcja)
- Sprawdź, czy **Settings → Resilience → Provider Profiles** ma włączony auto-rate-limit
- Sprawdź, czy provider zwraca kody `429` lub nagłówki `Retry-After`
### Dostrajanie exponential backoff
Profile providerów wspierają te ustawienia:
- **Base delay** — Początkowy czas oczekiwania po pierwszej awarii (domyślnie: 1s)
- **Max delay** — Górny limit czasu oczekiwania (domyślnie: 30s)
- **Multiplier** — O ile zwiększać opóźnienie przy kolejnych awariach (domyślnie: 2x)
### Anti-thundering herd
Gdy wiele równoległych żądań trafia w providera z limitem zapytań, OmniRoute używa mutexa + auto rate-limiting, aby serializować żądania i zapobiegać awariom kaskadowym. Działa to automatycznie dla providerów z kluczem API.
---
## Opcjonalna taksonomia awarii RAG / LLM (16 problemów)
Część użytkowników OmniRoute stawia bramkę przed stackami RAG lub agentów. W takich setupach często widać dziwny wzorzec: OmniRoute wygląda na zdrowe (providery w górze, profile routingu OK, brak alertów rate limit), a ostateczna odpowiedź i tak jest błędna.
W praktyce te incydenty zwykle pochodzą z downstreamowego pipeline'u RAG, a nie z samej bramki.
Jeśli chcesz wspólnego słownika do opisu tych awarii, możesz użyć WFGY ProblemMap — zewnętrznego zasobu tekstowego na licencji MIT, który definiuje szesnaście powtarzających się wzorców awarii RAG / LLM. Na wysokim poziomie obejmuje:
- drift retrieval i zerwane granice kontekstu
- puste lub nieaktualne indeksy i magazyny wektorów
- niedopasowanie embeddingów do semantyki
- składanie promptów i problemy z oknem kontekstu
- zapaść logiki i nadmiernie pewne odpowiedzi
- awarie długich łańcuchów i koordynacji agentów
- dryf pamięci i ról w multi-agent
- problemy z deploymentem i kolejnością bootstrapu
Idea jest prosta:
1. Gdy badziesz złą odpowiedź, zbierz:
- zadanie użytkownika i żądanie
- trasę lub combo providerów w OmniRoute
- kontekst RAG użyty downstream (pobrane dokumenty, tool calls itd.)
2. Zmapuj incydent na jeden lub dwa numery WFGY ProblemMap (`No.1` … `No.16`).
3. Zapisz numer we własnym dashboardzie, runbooku lub trackerze incydentów obok logów OmniRoute.
4. Użyj odpowiadającej strony WFGY, by zdecydować, czy zmienić stack RAG, retriever, czy strategię routingu.
Pełny tekst i konkretne przepisy są tutaj (licencja MIT, tylko tekst):
- [WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
Możesz zignorować tę sekcję, jeśli nie uruchamiasz pipeline'ów RAG ani agentów za OmniRoute.
---
## Znane problemy v3.8.0
Problemy specyficzne dla wydania v3.8.0 i ich obecne obejścia. Gdy poprawka wejdzie w późniejszym patchu, wpis zostanie zaktualizowany lub usunięty.
### Błędy auth Devin CLI
**Objawy:**
- "Devin CLI not found" lub "auth failed" przy wywoływaniu narzędzi opartych o Devin
- Sprawdzenie runtime CLI raportuje `installed=false`
**Przyczyny:**
- `CLI_DEVIN_BIN` wskazuje na nieistniejącą ścieżkę
- Devin CLI nie jest zainstalowany na hoście
**Naprawa:**
1. Zainstaluj Devin CLI dla swojej platformy
2. Ustaw `CLI_DEVIN_BIN=/usr/local/bin/devin` (lub rzeczywistą ścieżkę) w `.env`
3. Zrestartuj OmniRoute i przetestuj ponownie w **Dashboard → CLI Tools**
### Cooldown modelu utknął (ręczny reset)
**Objawy:**
- Model pozostaje na liście cooldown nawet po upływie czasu wygaśnięcia
- Żądania nadal pomijają model w routingu combo mimo że znacznik czasu jest w przeszłości
**Ręczny reset:**
- **Dashboard:** **Settings → Model Cooldowns** → kliknij **Re-enable** na dotkniętej karcie
- **API:** `DELETE /api/resilience/model-cooldowns` z nagłówkami auth zarządzania
### Połączenie providera Command Code kończy się 403
**Objawy:**
- 403 przy testowaniu połączenia providera Command Code
- Karta providera pokazuje "unauthorized" po świeżym dodaniu
**Przyczyna:** Przepływ OAuth nie zakończył się (callback nieodebrany lub token niezapisany).
**Naprawa:**
- Uruchom `omniroute providers` z CLI, aby ponownie wywołać przepływ OAuth, albo
- Ponów OAuth z **Dashboard → Providers → Command Code → Reconnect**
### ModelScope zwraca agresywne cooldowny 429
**Objawy:**
- Bardzo krótkie lub natychmiastowe cooldowny na ModelScope po małej serii żądań
- Routing combo pomija ModelScope wcześniej niż oczekiwano
**Przyczyna:** ModelScope emituje specyficzne dla providera nagłówki `Retry-After`. v3.8.0 zawiera dedykowaną obsługę tych nagłówków, więc starsze wersje odczytują je jako generyczne wskazówki rate-limit.
**Naprawa:**
- Upewnij się, że jesteś na v3.8.0 lub nowszej
- Sprawdź, że przełącznik `useUpstream429BreakerHints` jest włączony w **Settings → Resilience**
### Brak OMNIROUTE_WS_BRIDGE_SECRET w produkcji
**Objawy:**
- 401 na każdym żądaniu mostka WebSocket Codex/Responses na zdalnym hoście produkcyjnym
- Handshake mostka WebSocket zamyka się natychmiast po połączeniu
**Przyczyna:** Zmienna środowiskowa `OMNIROUTE_WS_BRIDGE_SECRET` nie jest ustawiona w środowisku produkcyjnym.
**Naprawa:**
1. Wygeneruj losowy sekret: `openssl rand -hex 32`
2. Ustaw `OMNIROUTE_WS_BRIDGE_SECRET=<random-secret>` w env serwera produkcyjnego (oraz każdego klienta łączącego się z mostkiem)
3. Zrestartuj OmniRoute
### Responses API: tryb background zdegradowany do synchronicznego
**Objawy:**
- Zalogowane ostrzeżenie: `background mode degraded to synchronous`
- Żądanie z `background: true` zwraca zwykłą odpowiedź synchroniczną zamiast uchwytu zadania w tle
**Przyczyna:** v3.8.0 celowo degraduje `background: true` w Responses API do wykonania synchronicznego z ostrzeżeniem. Pełne asynchroniczne wykonanie w tle to przyszła funkcjonalność.
**Naprawa:**
- Dostosuj klienta, aby wywoływał bez `background`, albo
- Poczekaj na późniejsze wydanie z pełnym trybem async background (śledź changelog)
---
## Nadal utknąłeś?
- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **Architektura**: Zobacz [`docs/architecture/ARCHITECTURE.md`](../architecture/ARCHITECTURE.md) po szczegóły wewnętrzne
- **API Reference**: Zobacz [`docs/reference/API_REFERENCE.md`](../reference/API_REFERENCE.md) po wszystkie endpointy
- **Health Dashboard**: Sprawdź **Dashboard → Health** pod kątem statusu systemu w czasie rzeczywistym
- **Translator**: Użyj **Dashboard → Translator** do debugowania problemów z formatami

View File

@@ -11,6 +11,10 @@ title: "Quality Gate Playbook"
>
> Benchmarks: OWASP DSOMM · OpenSSF Scorecard · SLSA · SonarQube "Clean as You Code" ·
> Quality-Ratchet pattern · DORA 2024 · OWASP LLM Top 10 (2025) · mutation-testing best practices.
>
> For the gate-by-gate authoritative reference (what each gate validates, CI job, ratchet vs
> policy, blocking vs advisory), see the
> [Quality Gates Reference](../architecture/QUALITY_GATES.md).
---

View File

@@ -123,3 +123,99 @@ If you changed the credential contract (new storage key, new cookie name, change
| Token missing from live request | Request is not authenticated | Sign in and send a chat message first |
| 401 after Test Connection passed | Expired or rotated session | Re-copy from a fresh live request |
| Chunked token fails | Only one chunk pasted | Select all `__Secure-next-auth.session-token.*` chunks |
---
## ChatGPT Web (Codex)
`ChatGPT Web (Codex)` is an additional provider. The existing
`ChatGPT Web (Plus/Pro)` provider described above stays unchanged for regular
chats, images, and its existing tool emulation.
### Prerequisites
- a full Cookie header from a signed-in ChatGPT session;
- Chrome or Chromium for npm, systemd, and PM2 installs;
- with the Docker `web` profile, the internal Chromium service from `docker-compose.yml`;
- an OpenAI tunnel and a ChatGPT custom connector for local Codex tools.
The tunnel is only needed for tool turns. `pro` is read-only and does not need a
local tool connector.
### Dashboard setup
1. Open the **ChatGPT Web (Codex)** provider and add a connection.
2. Paste the full ChatGPT cookie, the tunnel ID, the runtime key, and the name of
the custom connector.
3. Start the check. OmniRoute opens a headless Temporary Chat and also detects
whether `pro` is available for the account.
4. Save the connection. OmniRoute replaces the pasted cookie with the verified
Playwright storage state and stores it together with the runtime key through
the encrypted credential abstraction.
The raw cookie is not retained after a successful save. When the session expires,
open the connection, paste a fresh full cookie, and re-run the check. The doctor
status in the edit dialog reports browser, storage state, sign-in, Temporary
Chat, tunnel, connector, and tool round-trip separately.
### Models and combos
The fixed models are:
- `chatgpt-web-codex/instant`
- `chatgpt-web-codex/medium`
- `chatgpt-web-codex/high`
- `chatgpt-web-codex/extra-high`
- `chatgpt-web-codex/pro`
Add one of them to a combo like any other model. The Codex app sends only the
combo name as `model` to the regular Responses endpoint `/v1/responses`. There is
no special endpoint and no Codex-mode switch.
`pro` does not run local tools. A forced tool makes that combo target
incompatible; with optional tools the turn runs read-only and reports that
limitation as commentary.
### Security model
- The native path requires a Responses request, a recognized Codex client, and
matching thread and turn identities.
- Workspace, sandbox, approval policy, and the tool catalog come from the native
Codex shell. Free-form prompt text is not an authority for them.
- ChatGPT receives only a short-lived capability per turn. The MCP broker accepts
only tools that Codex offered in exactly that turn.
- Auto-confirming "Allow once" only returns the tool request to Codex. Codex
alone decides on approval and execution.
- Before the first output, the combo may fall back to another compatible target.
After that, provider, model, connection, and browser turn stay pinned until the
turn completes.
- Cookies, runtime keys, storage state, and capability tokens do not appear in
provider responses or request logs.
### Headless VPS and Docker
For npm, systemd, and PM2 installs, OmniRoute detects common Chrome and Chromium
paths. Alternatively, set `CHATGPT_WEB_CODEX_CHROME_PATH`.
The Docker `web` profile starts `chatgpt-web-codex-browser` on the internal
Compose network. Its CDP port is not published on the host. The protected profile
volume stays separate from the OmniRoute data volume, and the browser gets enough
shared memory. The internal CDP proxy listens only on the Compose network on port
`9223`; Chrome itself stays bound to loopback inside the sidecar.
A supervisor lease under `DATA_DIR` prevents multiple OmniRoute processes from
owning the same tunnel and broker state. A conflict shows up in the doctor.
### Interactive recovery
The normal path is fully headless. When ChatGPT demands an interactive sign-in or
challenge, the existing VNC browser infrastructure can be used as a recovery
path. Browser UI and CDP must then only be reachable over loopback, an
authenticated management connection, or an SSH tunnel; noVNC stays disabled in
normal operation.
### WebSocket fallback
When a combo contains `ChatGPT Web (Codex)`, the Responses WebSocket bridge
requests the HTTP/SSE fallback before connecting upstream. The actual transfer
then goes through `/v1/responses`.

View File

@@ -1,94 +0,0 @@
# ChatGPT Web (Codex)
`ChatGPT Web (Codex)` ist ein zusätzlicher Provider. Der bestehende Provider
`ChatGPT Web (Plus/Pro)` bleibt für normale Chats, Bilder und dessen bisherige
Tool-Emulation unverändert.
## Voraussetzungen
- ein vollständiger Cookie-Header einer angemeldeten ChatGPT-Sitzung;
- Chrome oder Chromium bei npm-, systemd- und PM2-Installationen;
- beim Docker-Profil `web` der interne Chromium-Dienst aus `docker-compose.yml`;
- ein OpenAI-Tunnel und ein ChatGPT-Custom-Connector für lokale Codex-Tools.
Der Tunnel ist nur für Tool-Runden nötig. `pro` ist read-only und benötigt keinen
lokalen Tool-Connector.
## Einrichtung in der Weboberfläche
1. Öffne den Provider `ChatGPT Web (Codex)` und füge eine Connection hinzu.
2. Füge den vollständigen ChatGPT-Cookie, die Tunnel-ID, den Runtime-Key und den
Namen des Custom Connectors ein.
3. Starte die Prüfung. OmniRoute öffnet headless einen Temporary Chat und erkennt
dabei auch, ob `pro` für das Konto verfügbar ist.
4. Speichere die Connection. OmniRoute ersetzt den eingegebenen Cookie durch den
geprüften Playwright-Storage-State und speichert ihn zusammen mit dem Runtime-Key
über die verschlüsselte Credential-Abstraktion.
Der rohe Cookie wird nach erfolgreichem Speichern nicht zusätzlich aufbewahrt.
Wenn die Sitzung abläuft, öffne die Connection, gib einen frischen vollständigen
Cookie ein und prüfe sie erneut. Der Doctor-Status im Edit-Dialog zeigt Browser,
Storage-State, Anmeldung, Temporary Chat, Tunnel, Connector und Tool-Roundtrip
getrennt an.
## Modelle und Combos
Die festen Modelle sind:
- `chatgpt-web-codex/instant`
- `chatgpt-web-codex/medium`
- `chatgpt-web-codex/high`
- `chatgpt-web-codex/extra-high`
- `chatgpt-web-codex/pro`
Füge eines davon wie jedes andere Modell zu einer Combo hinzu. Die Codex-App
sendet nur den Combo-Namen als `model` an den normalen Responses-Endpunkt
`/v1/responses`. Es gibt keinen Sonderendpoint und keinen Codex-Modus-Schalter.
`pro` führt keine lokalen Tools aus. Ein erzwungenes Tool macht dieses Combo-Ziel
inkompatibel; bei optionalen Tools läuft der Turn read-only und meldet diese
Einschränkung als Commentary.
## Sicherheitsmodell
- Der native Pfad verlangt einen Responses-Request, einen erkannten Codex-Client
sowie zusammenpassende Thread- und Turn-Identitäten.
- Workspace, Sandbox, Approval-Policy und Toolkatalog stammen aus der nativen
Codex-Hülle. Freier Prompttext ist dafür keine Autorität.
- ChatGPT erhält pro Turn nur eine kurzlebige Capability. Der MCP-Broker akzeptiert
ausschließlich Tools, die Codex in genau diesem Turn angeboten hat.
- Das automatische Bestätigen von „Allow once“ gibt nur den Tool-Wunsch an Codex
zurück. Codex allein entscheidet über Freigabe und Ausführung.
- Vor dem ersten Output darf die Combo auf ein anderes kompatibles Ziel fallen.
Danach bleiben Provider, Modell, Connection und Browserturn bis zum Abschluss
gepinnt.
- Cookies, Runtime-Keys, Storage-State und Capability-Tokens erscheinen nicht in
Providerantworten oder Request-Logs.
## Headless VPS und Docker
Bei npm-, systemd- und PM2-Betrieb erkennt OmniRoute übliche Chrome- und
Chromium-Pfade. Alternativ kann `CHATGPT_WEB_CODEX_CHROME_PATH` gesetzt werden.
Das Docker-Profil `web` startet `chatgpt-web-codex-browser` im internen
Compose-Netz. Sein CDP-Port wird nicht auf dem Host veröffentlicht. Das geschützte
Profilvolume bleibt getrennt vom OmniRoute-Datenvolume und der Browser erhält
ausreichend Shared Memory. Der interne CDP-Proxy lauscht nur im Compose-Netz auf
Port `9223`; Chrome selbst bleibt im Sidecar an Loopback gebunden.
Eine Supervisor-Lease unter `DATA_DIR` verhindert, dass mehrere OmniRoute-Prozesse
denselben Tunnel- und Brokerzustand besitzen. Ein Konflikt erscheint im Doctor.
## Interaktive Wiederherstellung
Der normale Pfad ist vollständig headless. Wenn ChatGPT eine interaktive
Anmeldung oder Challenge verlangt, kann die bestehende VNC-Browser-Infrastruktur
als Recovery-Weg verwendet werden. Browser-UI und CDP dürfen dabei nur über
Loopback, eine authentifizierte Managementverbindung oder einen SSH-Tunnel
erreichbar sein; noVNC bleibt im normalen Betrieb deaktiviert.
## WebSocket-Fallback
Enthält eine Combo `ChatGPT Web (Codex)`, fordert die Responses-WebSocket-Brücke
vor der Upstream-Verbindung den HTTP/SSE-Fallback an. Die eigentliche Übertragung
erfolgt dann über `/v1/responses`.