From 1442c47bbb68383fc4a1c7295898cc8823d37274 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Thu, 9 Apr 2026 15:55:59 -0300 Subject: [PATCH] =?UTF-8?q?chore(release):=20v3.5.6=20=E2=80=94=20email=20?= =?UTF-8?q?masking,=20model=20toggle,=20OpenRouter=20registries=20&=20bug?= =?UTF-8?q?=20fixes=20(#1080)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(minimax): switch auth from x-api-key to Authorization Bearer (#1076) Integrated into release/v3.5.6 — MiniMax auth fix with authHeader consistency normalization * feat(CI,i18n): autogenerate language files + Add missing strings (#1071) Integrated into release/v3.5.6 — i18n translations for memory, skills, and missing keys across 31 languages * fix(ci): restore i18n continue-on-error, remove auto-commit race condition * fix(husky): load nvm in hooks for VS Code compatibility * fix(husky): gracefully skip hooks when npm is not in PATH * fix: convert OpenAI function tool_choice to Claude tool format (#1072) * fix: prevent EPIPE feedback loop filling logs at GB/s (#1006) * fix: fallback to native fetch when undici dispatcher fails (#1054) * fix: improve Qoder PAT validation with actionable error messages (#966) - Add QODER_PERSONAL_ACCESS_TOKEN env var fallback for both validation and execution - Pre-flight ping check to diagnose connectivity issues (Docker/proxy) - Detect encrypted auth blobs from ~/.qoder/.auth/user and guide to website PAT - Clear error messages for auth failures with link to integrations page - Treat non-auth 4xx as auth-pass (request format issue, not token issue) - Update tests to cover new validation paths (23 tests, all passing) * feat: Improve the Chinese translation (#1079) Integrated into release/v3.5.6 * chore(release): v3.5.6 — i18n updates and credential security fixes * fix(ci): resolve e2e and docs-sync pipeline failures * fix(security): bump next to 16.2.3 to resolve SNYK-JS-NEXT-15954202 * fix: guard Memory/Cache UI against null toLocaleString crash (#1083) * fix: translate OpenAI tool_choice type 'function' to Claude 'tool' format (#1072) * fix: pass custom baseUrl in provider API key validation (#1078) * docs: update CHANGELOG with v3.5.6 bug fixes and security patches * docs: rewrite implement-features workflow with 5-phase harvest-research-report-plan-execute pipeline * docs: organize _ideia/ into viable/defer/notfit + add Phase 2.5 auto-response workflow * docs: implementation plans for #1025, #750, #960, #1046 + close already-implemented #833, #973, #982 * feat: mask email addresses in dashboard for privacy (#1025) * feat: add OpenRouter and GitHub to embedding/image provider registries (#960) * feat: add model visibility toggle and search filter to provider page (#750) * docs: move implemented features to notfit, update task plans status * chore: untrack _ideia/ and _tasks/ from git — private/internal only * chore(release): bump to v3.5.6 — changelog, docs, version sync & any-budget fix * fix: remove explicit .ts extension in qoderCli import that caused 500 error in production build --------- Co-authored-by: Jean Brito Co-authored-by: zenobit Co-authored-by: diegosouzapw Co-authored-by: Ethan Hunt <136065060+only4copilot@users.noreply.github.com> --- .agents/workflows/implement-features.md | 724 +++++++++++++++--- .env.example | 95 ++- .husky/pre-commit | 7 + .husky/pre-push | 7 + CHANGELOG.md | 30 + README.md | 48 +- docs/API_REFERENCE.md | 22 +- docs/ARCHITECTURE.md | 19 +- docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/TROUBLESHOOTING.md | 28 +- docs/USER_GUIDE.md | 4 +- docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/ar/README.md | 49 +- docs/i18n/ar/docs/ARCHITECTURE.md | 21 +- docs/i18n/ar/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/ar/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/ar/docs/USER_GUIDE.md | 4 +- docs/i18n/ar/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/bg/README.md | 49 +- docs/i18n/bg/docs/ARCHITECTURE.md | 21 +- docs/i18n/bg/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/bg/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/bg/docs/USER_GUIDE.md | 12 +- docs/i18n/bg/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/cs/README.md | 49 +- docs/i18n/cs/docs/ARCHITECTURE.md | 21 +- docs/i18n/cs/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/cs/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/cs/docs/USER_GUIDE.md | 12 +- docs/i18n/cs/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/da/README.md | 49 +- docs/i18n/da/docs/ARCHITECTURE.md | 21 +- docs/i18n/da/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/da/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/da/docs/USER_GUIDE.md | 12 +- docs/i18n/da/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/de/README.md | 49 +- docs/i18n/de/docs/ARCHITECTURE.md | 21 +- docs/i18n/de/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/de/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/de/docs/USER_GUIDE.md | 12 +- docs/i18n/de/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/es/README.md | 49 +- docs/i18n/es/docs/ARCHITECTURE.md | 21 +- docs/i18n/es/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/es/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/es/docs/USER_GUIDE.md | 12 +- docs/i18n/es/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/fi/README.md | 49 +- docs/i18n/fi/docs/ARCHITECTURE.md | 21 +- docs/i18n/fi/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/fi/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/fi/docs/USER_GUIDE.md | 12 +- docs/i18n/fi/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/fr/README.md | 49 +- docs/i18n/fr/docs/ARCHITECTURE.md | 21 +- docs/i18n/fr/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/fr/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/fr/docs/USER_GUIDE.md | 12 +- docs/i18n/fr/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/he/README.md | 49 +- docs/i18n/he/docs/ARCHITECTURE.md | 21 +- docs/i18n/he/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/he/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/he/docs/USER_GUIDE.md | 4 +- docs/i18n/he/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/hi/README.md | 49 +- docs/i18n/hi/docs/ARCHITECTURE.md | 21 +- docs/i18n/hi/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/hi/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/hi/docs/USER_GUIDE.md | 12 +- docs/i18n/hi/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/hu/README.md | 49 +- docs/i18n/hu/docs/ARCHITECTURE.md | 21 +- docs/i18n/hu/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/hu/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/hu/docs/USER_GUIDE.md | 12 +- docs/i18n/hu/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/id/README.md | 49 +- docs/i18n/id/docs/ARCHITECTURE.md | 21 +- docs/i18n/id/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/id/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/id/docs/USER_GUIDE.md | 12 +- docs/i18n/id/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/in/README.md | 49 +- docs/i18n/in/docs/ARCHITECTURE.md | 21 +- docs/i18n/in/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/in/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/in/docs/USER_GUIDE.md | 12 +- docs/i18n/in/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/it/README.md | 49 +- docs/i18n/it/docs/ARCHITECTURE.md | 21 +- docs/i18n/it/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/it/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/it/docs/USER_GUIDE.md | 12 +- docs/i18n/it/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/ja/README.md | 49 +- docs/i18n/ja/docs/ARCHITECTURE.md | 21 +- docs/i18n/ja/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/ja/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/ja/docs/USER_GUIDE.md | 12 +- docs/i18n/ja/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/ko/README.md | 49 +- docs/i18n/ko/docs/ARCHITECTURE.md | 21 +- docs/i18n/ko/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/ko/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/ko/docs/USER_GUIDE.md | 12 +- docs/i18n/ko/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/ms/README.md | 49 +- docs/i18n/ms/docs/ARCHITECTURE.md | 21 +- docs/i18n/ms/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/ms/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/ms/docs/USER_GUIDE.md | 12 +- docs/i18n/ms/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/nl/README.md | 49 +- docs/i18n/nl/docs/ARCHITECTURE.md | 21 +- docs/i18n/nl/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/nl/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/nl/docs/USER_GUIDE.md | 12 +- docs/i18n/nl/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/no/README.md | 49 +- docs/i18n/no/docs/ARCHITECTURE.md | 21 +- docs/i18n/no/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/no/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/no/docs/USER_GUIDE.md | 12 +- docs/i18n/no/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/phi/README.md | 49 +- docs/i18n/phi/docs/ARCHITECTURE.md | 21 +- docs/i18n/phi/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/phi/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/phi/docs/USER_GUIDE.md | 12 +- docs/i18n/phi/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/pl/README.md | 49 +- docs/i18n/pl/docs/ARCHITECTURE.md | 21 +- docs/i18n/pl/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/pl/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/pl/docs/USER_GUIDE.md | 12 +- docs/i18n/pl/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/pt-BR/README.md | 49 +- docs/i18n/pt-BR/docs/ARCHITECTURE.md | 21 +- .../i18n/pt-BR/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/pt-BR/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/pt-BR/docs/USER_GUIDE.md | 4 +- docs/i18n/pt-BR/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/pt/README.md | 49 +- docs/i18n/pt/docs/ARCHITECTURE.md | 21 +- docs/i18n/pt/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/pt/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/pt/docs/USER_GUIDE.md | 12 +- docs/i18n/pt/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/ro/README.md | 49 +- docs/i18n/ro/docs/ARCHITECTURE.md | 21 +- docs/i18n/ro/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/ro/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/ro/docs/USER_GUIDE.md | 12 +- docs/i18n/ro/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/ru/README.md | 49 +- docs/i18n/ru/docs/ARCHITECTURE.md | 21 +- docs/i18n/ru/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/ru/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/ru/docs/USER_GUIDE.md | 14 +- docs/i18n/ru/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/sk/README.md | 49 +- docs/i18n/sk/docs/ARCHITECTURE.md | 21 +- docs/i18n/sk/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/sk/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/sk/docs/USER_GUIDE.md | 12 +- docs/i18n/sk/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/sv/README.md | 49 +- docs/i18n/sv/docs/ARCHITECTURE.md | 21 +- docs/i18n/sv/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/sv/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/sv/docs/USER_GUIDE.md | 12 +- docs/i18n/sv/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/th/README.md | 49 +- docs/i18n/th/docs/ARCHITECTURE.md | 21 +- docs/i18n/th/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/th/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/th/docs/USER_GUIDE.md | 12 +- docs/i18n/th/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/tr/README.md | 49 +- docs/i18n/tr/docs/ARCHITECTURE.md | 21 +- docs/i18n/tr/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/tr/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/tr/docs/USER_GUIDE.md | 12 +- docs/i18n/tr/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/uk-UA/README.md | 49 +- docs/i18n/uk-UA/docs/ARCHITECTURE.md | 21 +- .../i18n/uk-UA/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/uk-UA/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/uk-UA/docs/USER_GUIDE.md | 12 +- docs/i18n/uk-UA/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/vi/README.md | 49 +- docs/i18n/vi/docs/ARCHITECTURE.md | 21 +- docs/i18n/vi/docs/CODEBASE_DOCUMENTATION.md | 2 +- docs/i18n/vi/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/vi/docs/USER_GUIDE.md | 12 +- docs/i18n/vi/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/i18n/zh-CN/README.md | 49 +- docs/i18n/zh-CN/docs/ARCHITECTURE.md | 21 +- .../i18n/zh-CN/docs/CODEBASE_DOCUMENTATION.md | 18 +- docs/i18n/zh-CN/docs/TROUBLESHOOTING.md | 30 +- docs/i18n/zh-CN/docs/USER_GUIDE.md | 10 +- docs/i18n/zh-CN/docs/VM_DEPLOYMENT_GUIDE.md | 2 +- docs/openapi.yaml | 2 +- electron/package.json | 2 +- llm.txt | 4 +- open-sse/config/embeddingRegistry.ts | 23 + open-sse/config/imageRegistry.ts | 15 + open-sse/config/providerRegistry.ts | 26 +- open-sse/executors/default.ts | 2 - open-sse/executors/qoder.ts | 3 + open-sse/mcp-server/server.ts | 3 +- open-sse/mcp-server/tools/advancedTools.ts | 3 +- open-sse/package.json | 2 +- open-sse/services/qoderCli.ts | 94 ++- .../translator/request/openai-to-claude.ts | 14 +- open-sse/utils/proxyFetch.ts | 20 +- package-lock.json | 98 +-- package.json | 7 +- scripts/bootstrap-env.mjs | 17 +- scripts/check-pr-test-policy.mjs | 27 +- scripts/check-t11-any-budget.mjs | 2 +- scripts/postinstall.mjs | 257 ++++--- scripts/sync-env.mjs | 137 ++++ scripts/validate_translation.py | 60 ++ .../cache/components/CacheEntriesTab.tsx | 2 +- src/app/(dashboard)/dashboard/memory/page.tsx | 4 +- .../dashboard/providers/[id]/page.tsx | 97 ++- .../cli-tools/openclaw/auto-order/route.ts | 3 +- src/app/api/providers/route.ts | 2 +- src/app/api/providers/validate/route.ts | 4 +- src/app/api/sync/initialize/route.ts | 3 +- src/app/api/system/version/route.ts | 145 ++++ src/i18n/messages/ar.json | 90 ++- src/i18n/messages/bg.json | 90 ++- src/i18n/messages/cs.json | 100 ++- src/i18n/messages/da.json | 90 ++- src/i18n/messages/de.json | 90 ++- src/i18n/messages/es.json | 90 ++- src/i18n/messages/fi.json | 90 ++- src/i18n/messages/fr.json | 90 ++- src/i18n/messages/he.json | 90 ++- src/i18n/messages/hi.json | 90 ++- src/i18n/messages/hu.json | 90 ++- src/i18n/messages/id.json | 90 ++- src/i18n/messages/it.json | 90 ++- src/i18n/messages/ja.json | 90 ++- src/i18n/messages/ko.json | 90 ++- src/i18n/messages/ms.json | 90 ++- src/i18n/messages/nl.json | 90 ++- src/i18n/messages/no.json | 90 ++- src/i18n/messages/phi.json | 90 ++- src/i18n/messages/pl.json | 90 ++- src/i18n/messages/pt-BR.json | 17 +- src/i18n/messages/pt.json | 17 +- src/i18n/messages/ro.json | 90 ++- src/i18n/messages/sk.json | 90 ++- src/i18n/messages/sv.json | 90 ++- src/i18n/messages/th.json | 90 ++- src/i18n/messages/tr.json | 90 ++- src/i18n/messages/uk-UA.json | 90 ++- src/i18n/messages/vi.json | 90 ++- src/i18n/messages/zh-CN.json | 331 +++++--- src/lib/a2a/skills/quotaManagement.ts | 3 +- src/lib/a2a/skills/smartRouting.ts | 3 +- src/lib/oauth/constants/oauth.ts | 34 +- src/lib/oauth/providers/gemini.ts | 6 +- src/lib/system/autoUpdate.ts | 82 +- src/mitm/server.cjs | 9 +- src/shared/components/OAuthModal.tsx | 2 +- src/shared/utils/logger.ts | 18 +- src/shared/utils/maskEmail.ts | 36 + src/shared/utils/resolveOmniRouteBaseUrl.ts | 24 + src/shared/utils/structuredLogger.ts | 47 +- src/shared/validation/schemas.ts | 1 + tests/unit/auto-update-runtime.test.mjs | 32 + tests/unit/auto-update.test.mjs | 140 +++- tests/unit/claude-oauth-provider.test.mjs | 21 +- tests/unit/mask-email.test.mjs | 51 ++ tests/unit/oauth-providers-config.test.mjs | 47 +- tests/unit/openrouter-registry.test.mjs | 83 ++ tests/unit/qoder-cli.test.mjs | 125 ++- tests/unit/qoder-executor.test.mjs | 25 +- tests/unit/qoder-oauth-config.test.mjs | 23 +- .../unit/resolve-omniroute-base-url.test.mjs | 52 ++ tests/unit/sync-env.test.mjs | 99 +++ 287 files changed, 6869 insertions(+), 2669 deletions(-) mode change 100644 => 100755 .husky/pre-commit create mode 100644 scripts/sync-env.mjs create mode 100644 src/shared/utils/maskEmail.ts create mode 100644 src/shared/utils/resolveOmniRouteBaseUrl.ts create mode 100644 tests/unit/mask-email.test.mjs create mode 100644 tests/unit/openrouter-registry.test.mjs create mode 100644 tests/unit/resolve-omniroute-base-url.test.mjs create mode 100644 tests/unit/sync-env.test.mjs diff --git a/.agents/workflows/implement-features.md b/.agents/workflows/implement-features.md index 460b665f2e..6a0938a868 100644 --- a/.agents/workflows/implement-features.md +++ b/.agents/workflows/implement-features.md @@ -2,23 +2,45 @@ description: Analyze open feature request issues, implement viable ones on dedicated branches, and respond to authors --- -# /implement-features — Feature Request Implementation Workflow +# /implement-features — Feature Request Harvest, Research & Implementation Workflow ## Overview -Fetches open feature request issues, analyzes each against the current codebase, implements viable ones **on the current release branch** (`release/vX.Y.Z`), and responds to authors with results. Does NOT merge to main — the release branch is later merged via PR. +A **5-phase** workflow that systematically harvests feature requests from GitHub issues, creates structured idea files, researches solutions across the internet and Git repositories, presents a consolidated report for user approval, then generates detailed implementation plans and executes them. -> **BRANCH RULE**: All work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `feat/` branches. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5. +**Output directory structure:** -## Steps +``` +_ideia/ +├── viable/ # Features approved for implementation +│ ├── need_details/ # ❓ Good idea but waiting for author clarification (issues stay OPEN) +│ │ └── 1015-warp-terminal-mitm.md +│ ├── 1046-native-playground.md # ✅ Ready — researched and planned +│ └── 1046-native-playground.requirements.md +├── defer/ # ⏭️ Good ideas deferred for future cycles (issues CLOSED) +│ └── 1041-smart-auto-combos.md +└── notfit/ # ❌ Out of scope / already exists (issues CLOSED) + └── 945-telegram-integration.md -### 1. Identify the Repository +_tasks/features-vX.Y.Z/ # Implementation plans (per-release) +└── 1046-native-playground.plan.md +``` + +> **LIFECYCLE RULE:** `viable/` files are **DELETED** once the feature is implemented — they are not moved. Only unimplemented features live in `viable/` (or `viable/need_details/`). Files in `defer/` and `notfit/` remain as permanent reference. + +> **BRANCH RULE**: All implementation work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `feat/` branches. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5. + +--- + +## Phase 1 — Harvest: Collect & Catalog Feature Ideas + +### 1.1 Identify the Repository // turbo -- Run: `git -C remote get-url origin` to extract owner/repo +- Run: `git -C remote get-url origin` to extract owner/repo. -### 2. Ensure Release Branch Exists +### 1.2 Ensure Release Branch Exists // turbo @@ -38,127 +60,647 @@ npm install If already on a `release/vX.Y.Z` branch, continue working there. -### 3. Fetch Open Feature Request Issues +### 1.3 Fetch ALL Open Feature Requests // turbo-all -**⚠️ CRITICAL**: The JSON output of `gh issue list` can be truncated by the tool, silently hiding issues and their comments. You MUST use the two-step approach below to guarantee **all** feature requests and their full conversations are fetched. +**⚠️ CRITICAL**: The JSON output of `gh issue list` can be truncated by the tool, silently hiding issues. You MUST use the two-step approach below. -**Step 3a — Get Issue numbers only** (small output, never truncated): +**Step 1 — Get Issue numbers only** (small output, never truncated): -- Run: `gh issue list --repo / --state open --labels "enhancement" --limit 500 --json number --jq '.[].number'` -- (Also run the same for `--labels "feature"` if they are separated, or filter all open issues if labels are not strictly used). -- This outputs one issue number per line. Count them and confirm total. +```bash +# Fetch issues with feature/enhancement labels +gh issue list --repo / --state open -l "enhancement" --limit 500 --json number --jq '.[].number' -**Step 3b — Fetch full metadata & conversations for each Issue** (one call per issue): +# Also check for [Feature] in title (common pattern when no labels are set) +gh issue list --repo / --state open --limit 500 --json number,title --jq '.[] | select(.title | test("\\[Feature\\]|\\[feature\\]|feature request"; "i")) | .number' +``` -- For each issue number from step 3a, run: - `gh issue view --repo / --json number,title,labels,body,comments,createdAt,author` -- Read not just the body, but **ALL comments (`comments` array)** completely to understand the full context, agreements, and restrictions discussed by the community. +- Merge both lists, deduplicate. Count and confirm the total. + +**Step 2 — Fetch full metadata for each Issue** (one call per issue): + +```bash +gh issue view --repo / --json number,title,labels,body,comments,createdAt,author,assignees +``` + +- Read the **entire body** — including description, use cases, screenshots, mockups, and any embedded images. +- Read **ALL comments** — community discussion, agreements, restrictions, owner responses, and linked PRs. +- **Images**: If the body or comments contain image URLs (`![...](...)` or `https://...png/jpg/gif`), note them — they may contain UI mockups, wireframes, or architecture diagrams that are essential to understanding the request. - You may batch these into parallel calls (up to 4 at a time). -- Filter for issues that are feature requests (if not already filtered by label). -- Sort by oldest first. +- Sort by oldest first (FIFO). -### 4. Analyze Each Feature Request +### 1.4 Create Idea Files (initially in `_ideia/` root) -For each feature request issue, perform a **two-level analysis**: +For each feature request, create a structured idea file in `/_ideia/`: -#### Level 1 — Viability Assessment +**Filename convention**: `-.md` +Example: `1046-native-playground.md`, `1041-smart-auto-combos.md` -Ask yourself: +#### 1.4a — If the idea file does NOT exist yet, create it: -- Does this feature align with the project's goals and architecture? -- Is the request technically feasible with the current codebase? -- Does it duplicate existing functionality? -- Would it introduce breaking changes or security risks? -- Is there enough detail to implement it? +```markdown +# Feature: + +> GitHub Issue: #<NUMBER> — opened by @<author> on <date> +> Status: 📋 Cataloged | Priority: TBD + +## 📝 Original Request + +<Paste the FULL issue body here, preserving all formatting, images, and code blocks> + +## 💬 Community Discussion + +<Summarize ALL comments chronologically, noting who said what and any decisions or objections raised> + +### Participants + +- @<author> — Original requester +- @<commenter1> — <brief role/opinion> +- ... + +### Key Points + +- <bullet list of the most important discussion points> +- <agreements reached> +- <objections raised> + +## 🎯 Refined Feature Description + +<YOUR interpretation and enrichment of the feature request. Expand on what was asked, fill in logical gaps, provide concrete examples of how it would work. This section should be MORE detailed and clearer than the original request.> + +### What it solves + +- <problem 1> +- <problem 2> + +### How it should work (high level) + +1. <step 1> +2. <step 2> +3. ... + +### Affected areas + +- <list of codebase areas, modules, files likely affected> + +## 📎 Attachments & References + +- <any image URLs, mockup links, or external references from the issue> + +## 🔗 Related Ideas + +- <links to related \_ideia/ files if any overlap found> +``` + +#### 1.4b — If the idea file ALREADY exists, update it: + +- Append new comments from the issue to the **Community Discussion** section. +- Update the **Refined Feature Description** if new information changes the understanding. +- Add any new **Related Ideas** cross-references found. +- **Do NOT overwrite** existing content — append and enrich it. + +### 1.5 Cross-Reference & Deduplication + +After processing all issues: + +- Scan all `_ideia/*.md` files for overlapping features. +- If two features are substantially the same, add `🔗 Related Ideas` cross-references to both. +- If one is a strict subset of another, note it in the smaller file: `> ℹ️ This feature is a subset of #<OTHER_NUMBER>. Consider implementing together.` + +--- + +## Phase 2 — Research: Find Solutions & Build Requirements + +For each cataloged idea that is **viable** (aligns with the project's goals): + +### 2.1 Viability Pre-Check + +Before investing in research, quickly assess: + +- [ ] Does this feature align with the project's goals and architecture? +- [ ] Is it technically feasible with the current codebase? +- [ ] Does it duplicate existing functionality? +- [ ] Would it introduce breaking changes or security risks? +- [ ] Is there enough detail to understand what's needed? **Verdict options:** -1. ✅ **VIABLE** — Makes sense, enough detail to implement → Go to Level 2 -2. ❓ **NEEDS MORE INFO** — Good idea but insufficient detail → Post comment asking for specifics -3. ❌ **NOT VIABLE** — Doesn't fit the project or is fundamentally flawed → Post comment explaining why, close issue +| Verdict | When | Action | +| --------------------- | ------------------------------------- | --------------------------- | +| ✅ **VIABLE** | Good idea, enough context | Proceed to Research | +| ❓ **NEEDS DETAIL** | Good idea, insufficient spec | Skip research, ask author | +| ⏭️ **DEFER** | Good idea, too complex for this cycle | Catalog only, skip research | +| ❌ **NOT FIT** | Doesn't fit the project | Explain why | +| 🔁 **ALREADY EXISTS** | Feature already implemented | Point to existing feature | -#### Level 2 — Implementation (only for VIABLE features) +### 2.2 Internet Research (for VIABLE features) -> **⚠️ ALL implementation happens on the release branch.** +For each viable feature, perform systematic research: -1. **Research** — Read all related source files to understand the current architecture -2. **Design** — Plan the implementation, filling gaps in the original request -3. **Implement** — Build the complete solution following project patterns, **on the release branch** -4. **Build** — Run `npm run build` to verify compilation -5. **Commit** — Commit with: `feat: <description> (#<NUMBER>)` -6. **Continue** — Move to the next feature (do not switch branches) +**Step 1 — Web search for similar implementations:** -### 5. Respond to Authors - -#### For VIABLE (implemented) features: - -// turbo -Post a comment on the issue: - -````markdown -## ✅ Feature Implemented! - -Hi @<author>! We've analyzed your request and implemented it. - -**Branch:** `release/vX.Y.Z` (upcoming release) - -### What was implemented: - -- <bullet list of what was done> - -### How to try it: - -```bash -git fetch origin -git checkout release/vX.Y.Z -npm install && npm run dev +``` +search_web("how to implement <feature description> in <tech stack>") +search_web("<feature keyword> implementation nextjs typescript 2025 2026") +search_web("<feature keyword> open source library npm") ``` -### Next steps: +**Step 2 — Find reference Git repositories:** -1. **Test it** — Please verify it works as you expected -2. **Want to improve it?** — Feel free to open a follow-up PR targeting `release/vX.Y.Z` -3. **Not quite right?** — Let us know in this issue what needs to change +``` +search_web("site:github.com <feature keyword> <tech stack> stars:>100") +search_web("github <feature keyword> implementation recently updated 2026") +``` -This will be included in the next release. Looking forward to your feedback! 🚀 +- Find **up to 10 relevant repositories**, sorted by most recently updated. +- For each repository: + - Note the repo URL, star count, last commit date + - Read its README and relevant source files via `read_url_content` + - Extract the architectural approach, patterns used, and key code snippets + +**Step 3 — Read API docs and standards:** + +If the feature involves an external API, protocol, or standard: + +- Find and read the official documentation +- Note version requirements, authentication patterns, rate limits + +### 2.3 Create Requirements File + +For each researched feature, create a requirements file alongside its idea file: + +**Filename**: `<NUMBER>-<kebab-case-short-title>.requirements.md` + +```markdown +# Requirements: <Feature Title> + +> Feature Idea: [#<NUMBER>](./<NUMBER>-<kebab-case-short-title>.md) +> Research Date: <YYYY-MM-DD> +> Verdict: ✅ VIABLE + +## 🔍 Research Summary + +<Brief summary of what was found during research> + +## 📚 Reference Implementations + +| # | Repository | Stars | Last Updated | Approach | Relevance | +| --- | ---------------- | ----- | ------------ | -------- | ------------ | +| 1 | [repo/name](url) | ⭐ N | YYYY-MM-DD | <brief> | High/Med/Low | +| 2 | ... | | | | | + +### Key Patterns Found + +- <pattern 1 with code snippet or link> +- <pattern 2> + +## 📐 Proposed Solution Architecture + +### Approach + +<Describe the chosen approach based on research findings> + +### New Files + +| File | Purpose | +| --------------------- | ------------- | +| `path/to/new/file.ts` | <description> | + +### Modified Files + +| File | Changes | +| -------------------------- | -------------- | +| `path/to/existing/file.ts` | <what changes> | + +### Database Changes + +- <migrations needed, if any> + +### API Changes + +- <new/modified endpoints, if any> + +### UI Changes + +- <new/modified pages/components, if any> + +## ⚙️ Implementation Effort + +- **Estimated complexity**: Low / Medium / High / Very High +- **Estimated files changed**: ~N +- **Dependencies needed**: <new npm packages, if any> +- **Breaking changes**: Yes/No — <details> +- **i18n impact**: <number of new translation keys> +- **Test coverage needed**: <brief description> + +## ⚠️ Open Questions + +- <question 1> +- <question 2> + +## 🔗 External References + +- <documentation URLs> +- <API references> +``` + +--- + +## Phase 2.5 — Organize & Respond: Sort Files and Post GitHub Comments + +### 2.5.1 Create Directory Structure + +// turbo + +```bash +mkdir -p <project_root>/_ideia/viable +mkdir -p <project_root>/_ideia/viable/need_details +mkdir -p <project_root>/_ideia/defer +mkdir -p <project_root>/_ideia/notfit +``` + +### 2.5.2 Move Idea Files to Category Subdirectories + +After classification, move EVERY idea file to its correct subdirectory: + +```bash +# ✅ VIABLE — move idea + requirements files +mv _ideia/<NUMBER>-*.md _ideia/viable/ +mv _ideia/<NUMBER>-*.requirements.md _ideia/viable/ + +# ❓ NEEDS DETAIL — viable but waiting for author response +mv _ideia/<NUMBER>-*.md _ideia/viable/need_details/ + +# ⏭️ DEFER — move idea files only +mv _ideia/<NUMBER>-*.md _ideia/defer/ + +# ❌ NOT FIT & 🔁 ALREADY EXISTS — move idea files only +mv _ideia/<NUMBER>-*.md _ideia/notfit/ +``` + +No files should remain in `_ideia/` root after this step (except subdirectories). + +### 2.5.3 Post GitHub Comments by Category + +**Each category has a specific comment template and action:** + +--- + +#### For 🔁 ALREADY EXISTS — Comment + CLOSE issue + +// turbo + +The feature already exists in the system. Explain WHERE it is and HOW to use it. + +```markdown +Hi @<author>! Thanks for the suggestion! 🙏 + +Great news — this functionality **already exists** in OmniRoute: + +**📍 Where to find it:** <exact dashboard path or settings location> + +**🔧 How to use it:** + +1. <step 1> +2. <step 2> +3. <step 3> + +If you have any trouble finding or using it, feel free to ask in a Discussion. We're always happy to help! + +Closing this as the feature is already available. 🎉 +``` + +```bash +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +``` + +--- + +#### For ⏭️ DEFER — Comment + CLOSE issue + +// turbo + +Thank the user, explain the idea was cataloged, and that we'll study it before implementing. + +```markdown +Hi @<author>! Thanks for this thoughtful feature request! 🙏 + +We really appreciate the detailed proposal. We've **cataloged your idea** and it's now part of our improvement backlog. + +Due to the **significant architectural impact** of this feature, we'll need to conduct thorough use-case studies and architectural analysis before we start development. This ensures we build it right and don't introduce regressions. + +**What happens next:** + +- Your idea is saved in our internal feature backlog +- We'll conduct architecture studies when this area is prioritized +- We'll notify you here when development begins + +Thank you for contributing to OmniRoute's roadmap! Your input helps shape the product. 🚀 +``` + +```bash +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +``` + +--- + +#### For ❌ NOT FIT — Comment + CLOSE issue + +// turbo + +Politely explain why the feature doesn't fit the project scope. + +```markdown +Hi @<author>! Thanks for the suggestion! 🙏 + +After careful analysis, we've determined that this feature **falls outside OmniRoute's core scope** as a proxy/router. + +**Reason:** <explain why — e.g., "Telegram integration belongs in the application/orchestrator layer that consumes OmniRoute's API, not inside the router itself."> + +**Alternative:** <suggest an alternative approach if possible> + +We appreciate you thinking of ways to improve OmniRoute! If you'd like to discuss this further, feel free to open a Discussion. 🙏 +``` + +```bash +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +``` + +--- + +#### For ❓ NEEDS DETAIL — Comment (keep OPEN) + +// turbo + +Ask for the specific missing details needed. + +```markdown +Hi @<author>! Thanks for the feature request — it's an interesting idea and we'd love to explore it further. 🙏 + +To move forward, we need a few more details: + +1. <specific question 1> +2. <specific question 2> +3. <specific question 3> + +If you know of any **open-source projects or repositories** that implement something similar, please share links — it would help us design the best solution. + +Looking forward to your response! 🚀 +``` + +--- + +#### For ✅ VIABLE — Comment (keep OPEN) + +// turbo + +Thank the user, confirm we've cataloged their idea, and explain it may be implemented in future versions. + +```markdown +Hi @<author>! Thanks for the great feature suggestion! 🙏 + +We've analyzed your request and it aligns well with OmniRoute's roadmap. We've **cataloged this feature** and it's in our implementation backlog. + +**Status:** 📋 Cataloged for future implementation + +This feature may be included in upcoming releases. We'll **respond to this issue and tag you** as soon as implementation begins so you can test it. + +Thank you for helping improve OmniRoute! 🚀 +``` + +**⚠️ Do NOT close viable issues — they remain OPEN for tracking.** + +--- + +## Phase 3 — Report: Present Findings to User + +### 3.1 🛑 MANDATORY STOP — Present Consolidated Report + +After completing Phase 1, Phase 2, and Phase 2.5, **STOP and present the following report** in the chat. Do NOT proceed to implementation. + +Present a structured report containing: + +#### 3.1a — Feature Summary Table + +| # | Issue | Title | Verdict | Location | Action | +| --- | ----- | ----- | --------------- | ----------------------------- | ----------------------------- | +| 1 | #N | Title | ✅ VIABLE | `_ideia/viable/` | Issue OPEN, comment posted | +| 2 | #N | Title | ⏭️ DEFER | `_ideia/defer/` | Issue CLOSED with explanation | +| 3 | #N | Title | ❌ NOT FIT | `_ideia/notfit/` | Issue CLOSED with explanation | +| 4 | #N | Title | 🔁 EXISTS | `_ideia/notfit/` | Issue CLOSED with guidance | +| 5 | #N | Title | ❓ NEEDS DETAIL | `_ideia/viable/need_details/` | Issue OPEN, questions posted | + +#### 3.1b — Viable Features Detail + +For each VIABLE feature, provide a brief paragraph: + +- What was found during research +- The proposed approach +- Key risks or unknowns +- Which reference repositories were most useful + +#### 3.1c — Issues Requiring Author Feedback + +For features marked ❓ NEEDS DETAIL, list: + +- What specific information is missing +- What examples or repository references would help + +#### 3.1d — Ask for User Confirmation + +End the report with: + +> **Ready to proceed with implementation?** +> +> - Reply **"sim"** or **"yes"** to generate full implementation plans for all VIABLE features. +> - Reply with specific issue numbers to select only certain features. +> - Reply **"não"** or **"no"** to stop here. + +--- + +## Phase 4 — Plan: Generate Implementation Plans (after user says "yes") + +> **⚠️ Do NOT enter this phase without explicit user approval from Phase 3.** + +### 4.1 Create Task Directory + +```bash +mkdir -p <project_root>/_tasks/features-vX.Y.Z/ +``` + +### 4.2 Generate One Implementation Plan Per Feature + +For each VIABLE feature approved by the user, create: + +**Filename**: `_tasks/features-vX.Y.Z/<NUMBER>-<kebab-case-title>.plan.md` + +```markdown +# Implementation Plan: <Feature Title> + +> Issue: #<NUMBER> +> Idea: [\_ideia/viable/<NUMBER>-title.md](../../_ideia/viable/<NUMBER>-title.md) +> Requirements: [\_ideia/viable/<NUMBER>-title.requirements.md](../../_ideia/viable/<NUMBER>-title.requirements.md) +> Branch: `release/vX.Y.Z` + +## Overview + +<Brief description of what will be built> + +## Pre-Implementation Checklist + +- [ ] Read all related source files listed below +- [ ] Confirm no conflicts with in-flight PRs +- [ ] Verify database migration numbering + +## Implementation Steps + +### Step 1: <Title> + +**Files:** + +- `path/to/file.ts` — <what to change> + +**Details:** +<Detailed description of the change, including code patterns to follow, function signatures, etc.> + +### Step 2: <Title> + +... + +### Step N: Tests + +**New test files:** + +- `tests/unit/<test-file>.test.mjs` — <what to test> + +**Test cases:** + +- [ ] <test case 1> +- [ ] <test case 2> + +### Step N+1: i18n + +**Translation keys to add:** + +- `<namespace>.<key>` — "<English value>" + +### Step N+2: Documentation + +- [ ] Update CHANGELOG.md +- [ ] Update relevant docs/ files + +## Verification Plan + +1. Run `npm run build` — must pass +2. Run `npm test` — all tests must pass +3. Run `npm run lint` — no new errors +4. <Manual verification steps> + +## Commit Plan +``` + +feat: <description> (#<NUMBER>) + +``` + +``` + +### 4.3 Present Plans for Final Approval + +Present a summary of all generated plans: + +> **Implementation plans generated:** +> +> | # | Feature | Plan File | Steps | Effort | +> | --- | ------- | ---------------------------------------- | ------- | ------ | +> | 1 | <title> | `_tasks/features-vX.Y.Z/N-title.plan.md` | N steps | Medium | +> +> Reply **"sim"** or **"yes"** to begin implementation of all features. +> Reply with specific issue numbers to implement only certain ones. + +--- + +## Phase 5 — Execute: Implement the Plans (after user says "yes") + +> **⚠️ Do NOT enter this phase without explicit user approval from Phase 4.** + +### 5.1 Implement Each Feature + +For each approved plan, execute it step by step: + +1. **Follow the plan** — implement exactly as specified in the `.plan.md` file +2. **Build** — Run `npm run build` after each feature to verify compilation +3. **Test** — Run `npm test` to ensure no regressions +4. **Commit** — Commit with: `feat: <description> (#<NUMBER>)` +5. **Update the plan** — Mark completed steps with `[x]` in the plan file +6. **Continue** — Move to the next feature (do NOT switch branches) + +### 5.2 Respond to Authors (Update Viable Issues) + +For each implemented feature, **close the issue with a final comment**: + +````markdown +✅ **Implemented in `release/vX.Y.Z`!** + +Hi @<author>! Great news — your feature request has been implemented! 🎉 + +**What was done:** + +- <bullet list of what was built> + +**How to try it:** + +```bash +git fetch origin && git checkout release/vX.Y.Z +npm install && npm run dev +``` ```` -#### For NEEDS MORE INFO: +This will be included in the upcoming **vX.Y.Z** release. Feel free to reopen if you spot any issues! 🚀 -// turbo -Post a comment asking for specific missing details needed to implement, e.g.: +```` -- "Could you describe the exact behavior when X happens?" -- "Which API endpoints should be affected?" -- "Should this apply to all providers or only specific ones?" +```bash +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +```` -Add the context of WHY you need each piece of information. +Then **DELETE the idea file** — it has served its purpose: -#### For NOT VIABLE: +```bash +# ✅ Implemented files are DELETED (not moved) +rm _ideia/viable/<NUMBER>-<title>.md +rm _ideia/viable/<NUMBER>-<title>.requirements.md # if exists +``` -// turbo -Post a polite comment explaining why the feature doesn't fit at this time: +> **Why delete?** `viable/` only holds features that still NEED to be done. Once implemented, the commit history and CHANGELOG are the source of truth. Keeping the file would be confusing. -- If the idea is decent but timing is wrong: "This is an interesting idea, but it doesn't align with our current priorities. Feel free to open a new issue with more details if you'd like us to reconsider." -- If fundamentally flawed: Explain the technical or architectural reasons why it won't work, suggest alternatives if possible. -- Close the issue after posting the comment. +### 5.3 Finalize & Push -### 6. Finalize & Push - -After implementing all viable features: +After implementing all approved features: 1. **Update CHANGELOG.md** on the release branch with all new feature entries 2. Push the release branch: `git push origin release/vX.Y.Z` 3. Run `/generate-release` workflow Phase 1 steps 7–10 (tests → commit → push → open PR to main → wait for user) -### 7. Summary Report +### 5.4 Final Summary Report -Present a summary report to the user via `notify_user`: +Present a final summary report to the user: -| Issue | Title | Verdict | Action | -| ----- | ----- | -------------- | ----------------------- | -| #N | Title | ✅ Implemented | Committed on release/vX | -| #N | Title | ❓ Needs Info | Comment posted | -| #N | Title | ❌ Not Viable | Closed with explanation | +| Issue | Title | Verdict | Action | Commit | +| ----- | ----- | --------------- | -------------------------------------------------- | --------- | +| #N | Title | ✅ Implemented | Issue closed, idea file deleted | `abc1234` | +| #N | Title | ⏭️ Deferred | Issue closed + saved in `_ideia/defer/` | — | +| #N | Title | ❌ Not Fit | Issue closed + saved in `_ideia/notfit/` | — | +| #N | Title | 🔁 Exists | Issue closed + saved in `_ideia/notfit/` | — | +| #N | Title | ❓ Needs Detail | Issue OPEN, moved to `_ideia/viable/need_details/` | — | + +Include: + +- Total features harvested +- Total ideas cataloged (`viable/need_details/` + `defer/` + `notfit/`) +- Total features implemented (idea files deleted, issues closed) +- Total features deferred +- Total issues closed +- Total issues left open (needs detail only — viable are closed after implementation) +- Test results (pass/fail count) diff --git a/.env.example b/.env.example index 5ff8b6acc8..5f83134ca5 100644 --- a/.env.example +++ b/.env.example @@ -11,7 +11,7 @@ API_KEY_SECRET= # Initial admin password — CHANGE THIS before first use! INITIAL_PASSWORD=CHANGEME -DATA_DIR=/var/lib/omniroute +# DATA_DIR=/var/lib/omniroute # Storage (SQLite) STORAGE_DRIVER=sqlite @@ -90,49 +90,70 @@ NEXT_PUBLIC_ENABLE_SOCKS5_PROXY=true # CLI_ROO_BIN=roo # CLI_CONTINUE_BIN=cn -# Provider OAuth Credentials (optional — override hardcoded defaults) -# These can also be set via data/provider-credentials.json -# CLAUDE_OAUTH_CLIENT_ID= +# Internal agent / tool integrations (optional) +# Used by the MCP server, A2A skills, and CLI sidecars when they need to call +# the running OmniRoute instance explicitly instead of relying on localhost. +# OMNIROUTE_BASE_URL=http://localhost:20128 +# OMNIROUTE_API_KEY= +# ROUTER_API_KEY= +# MODEL_SYNC_INTERVAL_HOURS=24 + +# ═══════════════════════════════════════════════════ +# OAUTH PROVIDER CREDENTIALS +# ═══════════════════════════════════════════════════ +# These are the built-in default credentials that work for localhost setups. +# For remote/VPS deployments, register your own credentials at each provider. +# The sync-env script will auto-populate these in your .env if missing. +# +# These can also be overridden via data/provider-credentials.json where supported. + +# ── Claude Code (Anthropic) ── +CLAUDE_OAUTH_CLIENT_ID=9d1c250a-e61b-44d9-88ed-5944d1962f5e + +# ── Codex / OpenAI ── +CODEX_OAUTH_CLIENT_ID=app_EMoamEEZ73f0CkXaXp7hrann + +# ── Gemini (Google) ── +GEMINI_OAUTH_CLIENT_ID=681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com +GEMINI_OAUTH_CLIENT_SECRET=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 + +# ── Gemini CLI (Google) ── +GEMINI_CLI_OAUTH_CLIENT_ID=681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com +GEMINI_CLI_OAUTH_CLIENT_SECRET=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 + +# ── Qwen (Alibaba) ── +QWEN_OAUTH_CLIENT_ID=f0304373b74a44d2b584a3fb70ca9e56 + +# ── Kimi Coding (Moonshot) ── +KIMI_CODING_OAUTH_CLIENT_ID=17e5f671-d194-4dfb-9706-5516cb48c098 + +# ── Antigravity (Google Cloud Code) ── +ANTIGRAVITY_OAUTH_CLIENT_ID=1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com +ANTIGRAVITY_OAUTH_CLIENT_SECRET=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 + +# ── GitHub Copilot ── +GITHUB_OAUTH_CLIENT_ID=Iv1.b507a08c87ecfe98 + +# ── Qoder ── +QODER_OAUTH_CLIENT_SECRET=4Z3YjXycVsQvyGF1etiNlIBB4RsqSDtW + +# ── Qoder (URLs — set these to enable Qoder OAuth login) ── +# QODER_OAUTH_AUTHORIZE_URL= +# QODER_OAUTH_TOKEN_URL= +# QODER_OAUTH_USERINFO_URL= +# QODER_OAUTH_CLIENT_ID= # ───────────────────────────────────────────────────────────────────────────── # ⚠️ GOOGLE OAUTH (Antigravity, Gemini CLI) — IMPORTANT FOR REMOTE SERVERS # ───────────────────────────────────────────────────────────────────────────── -# The built-in Google OAuth credentials ONLY work when OmniRoute runs on -# localhost (127.0.0.1 / local network). They are registered with -# redirect_uri = http://localhost:PORT/callback and Google will reject any -# other redirect URI with: redirect_uri_mismatch. -# -# If you are hosting OmniRoute on a remote server (VPS, Docker, cloud), you -# MUST register your own Google Cloud OAuth 2.0 credentials: -# +# The credentials above ONLY work when OmniRoute runs on localhost. +# If you are hosting OmniRoute on a remote server, register your own: # 1. Go to https://console.cloud.google.com/apis/credentials # 2. Create an OAuth 2.0 Client ID (type: "Web application") -# 3. Add your server URL as Authorized redirect URI: -# https://your-server.com/callback -# 4. Copy the Client ID and Client Secret below. -# -# See the full tutorial in README.md → "OAuth em Servidor Remoto" section. -# -# Antigravity (Google Gemini Code Assist): -# ANTIGRAVITY_OAUTH_CLIENT_ID=your-client-id.apps.googleusercontent.com -# ANTIGRAVITY_OAUTH_CLIENT_SECRET=GOCSPX-your-secret -ANTIGRAVITY_OAUTH_CLIENT_SECRET=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 - -# Gemini CLI (Google AI): -# GEMINI_OAUTH_CLIENT_ID=your-client-id.apps.googleusercontent.com -# GEMINI_OAUTH_CLIENT_SECRET=GOCSPX-your-secret -# GEMINI_CLI_OAUTH_CLIENT_ID= -GEMINI_OAUTH_CLIENT_SECRET=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 -GEMINI_CLI_OAUTH_CLIENT_SECRET=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 +# 3. Add your server URL as Authorized redirect URI +# 4. Replace the values above with your credentials. # ───────────────────────────────────────────────────────────────────────────── -# CLAUDE_OAUTH_CLIENT_ID= -# CODEX_OAUTH_CLIENT_ID= -# CODEX_OAUTH_CLIENT_SECRET= -# QWEN_OAUTH_CLIENT_ID= -# QODER_OAUTH_CLIENT_ID= -QODER_OAUTH_CLIENT_SECRET=4Z3YjXycVsQvyGF1etiNlIBB4RsqSDtW - # ───────────────────────────────────────────────────────────────────────────── # Provider User-Agent Overrides (optional — customize per-provider UA headers) # ───────────────────────────────────────────────────────────────────────────── @@ -206,7 +227,7 @@ GEMINI_CLI_USER_AGENT=google-api-nodejs-client/9.15.1 # API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS=0 # CORS configuration (default: * allows all origins) -# CORS_ORIGINS=* +# CORS_ORIGIN=* # Logging # APP_LOG_LEVEL=info diff --git a/.husky/pre-commit b/.husky/pre-commit old mode 100644 new mode 100755 index 342f766e3c..7fad3fc22f --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,3 +1,10 @@ +#!/usr/bin/env sh +if ! command -v npx >/dev/null 2>&1; then + echo "⚠️ npx not found in PATH — skipping pre-commit hooks" + echo " Run 'npm run lint && npm run check:any-budget:t11' manually before pushing." + exit 0 +fi + npx lint-staged node scripts/check-docs-sync.mjs npm run check:any-budget:t11 diff --git a/.husky/pre-push b/.husky/pre-push index 6d0a7660d3..4e35eb020c 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1 +1,8 @@ +#!/usr/bin/env sh +if ! command -v npm >/dev/null 2>&1; then + echo "⚠️ npm not found in PATH — skipping pre-push hooks" + echo " Run 'npm test' manually before pushing." + exit 0 +fi + npm run test:unit diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ade82dd8f..e6690b0f5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,36 @@ --- +## [3.5.6] — 2026-04-09 + +### ✨ New Features + +- **Email Privacy Masking:** OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots. Full address visible on hover via `title` attribute (#1025). +- **OpenRouter & GitHub in Embedding/Image Registries:** OpenRouter (3 embedding models, 4 image models) and GitHub Models (2 embedding models via Azure inference) are now first-class entries in the provider registries, enabling their use for `/v1/embeddings` and `/v1/images/generations` (#960). +- **Model Visibility Toggle & Search Filter:** The provider page model list now includes a real-time search/filter bar and a per-model visibility toggle (👁 icon). Hidden models are grayed out and excluded from the `/v1/models` catalog. An active-count badge (`N/M active`) shows at a glance how many models are enabled (#750). +- **Chinese Localization (zh-CN):** Added missing translations for Context Relay, Memory, LKGP, and Models.dev sync features, while standardizing terminology across the application (#1079). +- **Environment Auto-Sync:** Added `sync-env.mjs` to auto-generate and append `.env` from `.env.example` during installation, automatically generating cryptographic secrets on first run. +- **Source Mode Dashboard Update:** Fixed real-time Source (git-checkout) updating in the dashboard, enabling secure, real-time update pipelines for non-NPM installations. + +### 🐛 Bug Fixes & Security + +- **Hardcoded Secret Cleanup:** Removed 12 hardcoded OAuth credential fallbacks from the source code, forcing secure reliance on environment variables and resolving static analysis security alerts. +- **Next.js Security Patch:** Bumped `next` from 16.2.2 to 16.2.3 to resolve critical RSC deserialization RCE vulnerability (SNYK-JS-NEXT-15954202). +- **Memory/Cache UI Crash:** Added null-safety guards (`?? 0`) to `.toLocaleString()` calls in Memory and Cache dashboard pages, preventing `TypeError` crashes when database tables are empty or contain null numeric values (#1083). +- **WebSearch tool_choice Translation:** Fixed OpenAI-to-Claude translator dropping `tool_choice` objects with `type: "function"` as-is, which Claude rejects. Now properly maps all OpenAI `tool_choice` variants (`function`, `required`, `none`) to Claude-compatible format (`tool`, `any`, `auto`), fixing "Did 0 searches" in Claude Code WebSearch (#1072). +- **Provider Validation baseUrl Override:** Added `baseUrl` passthrough from frontend validation requests to the backend validation endpoint. Chinese-site users of Alibaba Coding Plan (bailian-coding-plan) can now validate API keys against their custom Base URL instead of always hitting the international endpoint (#1078). +- **Minimax Auth Header:** Switched Minimax provider from `x-api-key` to `Authorization: Bearer` header format, matching the current API spec (#1076). +- **Native Fetch Fallback:** Added graceful fallback to native `fetch` when the `undici` dispatcher fails, improving resilience in environments where undici is unavailable (#1054). +- **EPIPE Flood Fix:** Added circuit-breaker logic to prevent EPIPE errors from creating a feedback loop that fills logs at GB/s (#1006). +- **Qoder PAT Validation:** Improved Qoder Personal Access Token validation with actionable error messages that guide users to the correct token format (#966). +- **CI/CD Pipeline:** Fixed `check:docs-sync` failure by syncing OpenAPI version to 3.5.6 and finalizing CHANGELOG release heading. Commented out `DATA_DIR` in `.env.example` to prevent E2E test failures in CI runners lacking root permissions. + +### 🌍 i18n + +- **Auto Language Generation (CI):** Added CI pipeline to auto-generate missing language files and strings via `feat(CI,i18n)` workflow, covering 30+ locales (#1071). + +--- + ## [3.5.5] — 2026-04-08 ### ✨ New Features diff --git a/README.md b/README.md index 1e09af1a31..7bf3527b06 100644 --- a/README.md +++ b/README.md @@ -954,7 +954,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1308,13 +1308,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2190,22 +2190,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## 📖 Documentation -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/API_REFERENCE.md b/docs/API_REFERENCE.md index 3c5af34dad..62ef788305 100644 --- a/docs/API_REFERENCE.md +++ b/docs/API_REFERENCE.md @@ -68,7 +68,7 @@ Content-Type: application/json } ``` -Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA. +Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA, **OpenRouter**, **GitHub Models**. ```bash # List all embedding models @@ -91,7 +91,7 @@ Content-Type: application/json } ``` -Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI. +Available providers: OpenAI (DALL-E, GPT Image 1), xAI (Grok Image), Together AI (FLUX), Fireworks AI, Nebius (FLUX), Hyperbolic, NanoBanana, **OpenRouter**, SD WebUI (local), ComfyUI (local). ```bash # List all image models @@ -179,15 +179,15 @@ Response example: ### Provider Management -| Endpoint | Method | Description | -| ---------------------------- | --------------- | ------------------------ | -| `/api/providers` | GET/POST | List / create providers | -| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider | -| `/api/providers/[id]/test` | POST | Test provider connection | -| `/api/providers/[id]/models` | GET | List provider models | -| `/api/providers/validate` | POST | Validate provider config | -| `/api/provider-nodes*` | Various | Provider node management | -| `/api/provider-models` | GET/POST/DELETE | Custom models | +| Endpoint | Method | Description | +| ---------------------------- | --------------------- | ---------------------------------------------- | +| `/api/providers` | GET/POST | List / create providers | +| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider | +| `/api/providers/[id]/test` | POST | Test provider connection | +| `/api/providers/[id]/models` | GET | List provider models | +| `/api/providers/validate` | POST | Validate provider config | +| `/api/provider-nodes*` | Various | Provider node management | +| `/api/provider-models` | GET/POST/PATCH/DELETE | Custom models (add, update, hide/show, delete) | ### OAuth Flows diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index c76f482a06..c633c9d498 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -713,16 +713,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -761,7 +759,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -788,7 +787,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/CODEBASE_DOCUMENTATION.md b/docs/CODEBASE_DOCUMENTATION.md index 2cf0a7a607..1b16d67844 100644 --- a/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/CODEBASE_DOCUMENTATION.md @@ -403,7 +403,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. | | `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). | | `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. | -| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. | | `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. | diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 45f17164cd..e9d67d43a7 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -8,14 +8,14 @@ Common problems and solutions for OmniRoute. ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -29,6 +29,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -158,9 +159,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -175,8 +178,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md index 23ec2f65ac..e526d7c554 100644 --- a/docs/USER_GUIDE.md +++ b/docs/USER_GUIDE.md @@ -491,7 +491,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -522,7 +522,7 @@ post_install() { | `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Server-side refresh cadence for cached Provider Limits data; UI refresh buttons still trigger manual sync | | `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work | -| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) | | `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport for managed Quick Tunnels (`http2`, `quic`, or `auto`) | diff --git a/docs/VM_DEPLOYMENT_GUIDE.md b/docs/VM_DEPLOYMENT_GUIDE.md index ceee61ead4..7e968f90ee 100644 --- a/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/VM_DEPLOYMENT_GUIDE.md @@ -106,7 +106,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/ar/README.md b/docs/i18n/ar/README.md index 20338c5756..fe49c80a62 100644 --- a/docs/i18n/ar/README.md +++ b/docs/i18n/ar/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## التوثيق -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/ar/docs/ARCHITECTURE.md b/docs/i18n/ar/docs/ARCHITECTURE.md index ec6712920b..f9e96dbc6f 100644 --- a/docs/i18n/ar/docs/ARCHITECTURE.md +++ b/docs/i18n/ar/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/ar/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/ar/docs/CODEBASE_DOCUMENTATION.md index 53a026ad15..658d5d8c39 100644 --- a/docs/i18n/ar/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ar/docs/CODEBASE_DOCUMENTATION.md @@ -371,7 +371,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | "stream.ts" | **SSE Transform Stream**— خط أنابيب البث الأساسي. وضعان: "الترجمة" (ترجمة كاملة) و"العبور" (التطبيع + الطلب المستخدم). وأخذ بعين الاعتبار التخزين المؤقت للقطعة وتقدير استخدامها وتتبع طول الفيديو. تجنب مثيلات وحدة التشفير/وحدة فك التشفير لكل حالة DC المشتركة. | | `streamHelpers.ts` | SSE ذات المستوى المنخفض: `parseSSELine` (متسامح مع المسافات البيضاء)، `hasValuableContent` ( تصفية أدوات الفارغة لـ OpenAI/Claude/Gemini)، `fixInvalidId`، `formatSSE` (تسلسل SSE مدرك للتنسيق مع `perf_metrics`). | | `usageTracking.ts` | استخدام النسخة المميزة من أي تنسيق (Claude/OpenAI/Gemini/Responses)، والاستعانة بـ DNS لكل رمز مميز للأداة/الرسالة، والمخزن المؤقت (هامش أمان 2000 رمز مميز)، وتصفية الخاصيات بالتنسيق، وتسجيل وحدة التحكم مع ANSI. | -| `requestLogger.ts` | تسجيل الطلب إلى الملف (قم بالاشتراك عبر `ENABLE_REQUEST_LOGS=true`). ينشئ مجلدات الجلسة بملفات مرقمة: `1_req_client.json` → `7_res_client.txt`. كل عمليات الإدخال/الإخراج غير متزامنة (أطلق النار وانسى). داخل المسام. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | ويمثل خيارًا محددًا لـ Claude CLI (عنوان الإنتاج، والحماية، والعد) ويعيد ميزة دون الاتصال بأي مكان. يدعم كل من الدف وغير الدف. لذلك عمدا على نطاق كلود CLI. | | `networkProxy.ts` | يحل عنوان URL للوكلاء لموفر معين مع الأسبقية: تفعيل الخاص بالموفر → تفعيل العام → متغيرات البيئة (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). يدعم استثناءات `NO_PROXY`. اختيارية ذاكرة تخزين مؤقتة لمدة 30 ثانية. | #### خط أنابيب تدفق SSE```mermaid | diff --git a/docs/i18n/ar/docs/TROUBLESHOOTING.md b/docs/i18n/ar/docs/TROUBLESHOOTING.md index a56950cd98..4cc6002e7d 100644 --- a/docs/i18n/ar/docs/TROUBLESHOOTING.md +++ b/docs/i18n/ar/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/ar/docs/USER_GUIDE.md b/docs/i18n/ar/docs/USER_GUIDE.md index ba5148bc92..6a398eaf56 100644 --- a/docs/i18n/ar/docs/USER_GUIDE.md +++ b/docs/i18n/ar/docs/USER_GUIDE.md @@ -440,7 +440,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/بن/ش تصدير بورت = "$ {ميناء: -20128}" تصدير DATA_DIR = "${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -تصدير LOG_TO_FILE = "${LOG_TO_FILE:-false}" +تصدير APP_LOG_TO_FILE = "${APP_LOG_TO_FILE:-false}" مكدير -p "${DATA_DIR}" عقدة exec /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -470,7 +470,7 @@ EOF | `ALLOW_API_KEY_REVEAL` | `كاذبة` | السماح لـ Api Manager بنسخ مفاتيح API الكاملة عند الطلب | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | إيقاع التحديث من جانب الخادم لبيانات حدود الموفر المخزنة مؤقتًا؛ لا تزال أزرار تحديث واجهة المستخدم تؤدي إلى المزامنة اليدوية | | `DISABLE_SQLITE_AUTO_BACKUP` | `كاذبة` | تعطيل لقطات SQLite التلقائية قبل الكتابة/الاستيراد/الاستعادة؛ النسخ الاحتياطية اليدوية لا تزال تعمل | -| `ENABLE_REQUEST_LOGS` | `كاذبة` | تمكين سجلات الطلب/الاستجابة | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `كاذبة` | فرض ملف تعريف ارتباط المصادقة "الآمن" (خلف الوكيل العكسي HTTPS) | | `CLOUDFLARED_BIN` | غير محدد | استخدم ملفًا ثنائيًا موجودًا `cloudflared` بدلاً من التنزيل المُدار | | `CLOUDFLARED_PROTOCOL` | `http2` | النقل للأنفاق السريعة المُدارة (`http2` أو `quic` أو `auto`) | diff --git a/docs/i18n/ar/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ar/docs/VM_DEPLOYMENT_GUIDE.md index b406973464..5c65027747 100644 --- a/docs/i18n/ar/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/ar/docs/VM_DEPLOYMENT_GUIDE.md @@ -93,7 +93,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/bg/README.md b/docs/i18n/bg/README.md index 3445919355..f0bfe4f98d 100644 --- a/docs/i18n/bg/README.md +++ b/docs/i18n/bg/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Документация -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/bg/docs/ARCHITECTURE.md b/docs/i18n/bg/docs/ARCHITECTURE.md index 4bb4e676d5..dcd6d0ce59 100644 --- a/docs/i18n/bg/docs/ARCHITECTURE.md +++ b/docs/i18n/bg/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/bg/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/bg/docs/CODEBASE_DOCUMENTATION.md index 2f8f4f9855..26a56196cc 100644 --- a/docs/i18n/bg/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/bg/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— основният тръбопровод за стрийминг. Два режима: `TRANSLATE` (превод в пълен формат) и `PASSTHROUGH` (нормализиране + извличане на използването). Управлява буфериране на парчета, оценка на използването, проследяване на дължината на съдържанието. Екземплярите на енкодер/декодер на поток избягват споделено състояние. | | `streamHelpers.ts` | Помощни програми за SSE на ниско ниво: `parseSSELine` (толерантно към бели интервали), `hasValuableContent` (филтрира празни парчета за OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (съобразено с формат SSE сериализиране с почистване на `perf_metrics`). | | `usageTracking.ts` | Извличане на използване на токени от всеки формат (Claude/OpenAI/Gemini/Responses), оценка с отделни съотношения на инструмент/съобщение char-per-token, добавяне на буфер (марж за безопасност от 2000 токена), филтриране на специфично за формат поле, конзолно регистриране с ANSI цветове. | -| `requestLogger.ts` | Регистриране на заявки, базирани на файлове (включване чрез `ENABLE_REQUEST_LOGS=true`). Създава сесийни папки с номерирани файлове: `1_req_client.json` → `7_res_client.txt`. Всички I/O са асинхронни (задействай и забрави). Маскира чувствителните заглавки. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Прихваща специфични модели от Claude CLI (извличане на заглавие, загряване, броене) и връща фалшиви отговори, без да се обажда на доставчик. Поддържа както стрийминг, така и не стрийминг. Умишлено ограничен до Claude CLI обхват. | | `networkProxy.ts` | Разрешава изходящ URL адрес на прокси за даден доставчик с предимство: специфична за доставчика конфигурация → глобална конфигурация → променливи на средата (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Поддържа изключения `NO_PROXY`. Кешира конфигурацията за 30s. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/bg/docs/TROUBLESHOOTING.md b/docs/i18n/bg/docs/TROUBLESHOOTING.md index 45718fe147..12ad593839 100644 --- a/docs/i18n/bg/docs/TROUBLESHOOTING.md +++ b/docs/i18n/bg/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/bg/docs/USER_GUIDE.md b/docs/i18n/bg/docs/USER_GUIDE.md index 39b7fca5db..b8abb5ca7e 100644 --- a/docs/i18n/bg/docs/USER_GUIDE.md +++ b/docs/i18n/bg/docs/USER_GUIDE.md @@ -468,7 +468,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -500,7 +500,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `false` | Разрешаване на Api Manager да копира пълни API ключове при поискване | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Честота на опресняване от страна на сървъра за кеширани данни за ограниченията на доставчика; Бутоните за опресняване на потребителския интерфейс все още задействат ръчно синхронизиране | | `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Деактивирайте автоматичните моментни снимки на SQLite преди запис/импорт/възстановяване; ръчните архиви все още работят | -| `ENABLE_REQUEST_LOGS` | `false` | Разрешава регистрационни файлове за заявки/отговори | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `false` | Принудително `Secure` бисквитка за удостоверяване (зад HTTPS обратен прокси) | | `CLOUDFLARED_BIN` | деактивирано | Използвайте съществуващ двоичен файл `cloudflared` вместо управлявано изтегляне | | `CLOUDFLARED_PROTOCOL` | `http2` | Транспорт за управлявани бързи тунели (`http2`, `quic` или `auto`) | @@ -693,15 +693,15 @@ OmniRoute прилага устойчивост на ниво доставчик - Чувствителност на откриване на ограничение на скоростта - Параметри на експоненциално отстъпление -2.**Редактируеми ограничения на скоростта**— Настройки по подразбиране на системно ниво, които могат да се конфигурират в таблото за управление: -**Заявки в минута (RPM)**— Максимален брой заявки в минута за акаунт -**Минимално време между заявките**— Минимална разлика в милисекунди между заявките -**Максимални едновременни заявки**— Максимални едновременни заявки за акаунт + 2.**Редактируеми ограничения на скоростта**— Настройки по подразбиране на системно ниво, които могат да се конфигурират в таблото за управление: -**Заявки в минута (RPM)**— Максимален брой заявки в минута за акаунт -**Минимално време между заявките**— Минимална разлика в милисекунди между заявките -**Максимални едновременни заявки**— Максимални едновременни заявки за акаунт - Щракнете върху**Редактиране**, за да промените, след това върху**Запазване**или**Отказ**. Стойностите се запазват чрез API за устойчивост. -3.**Прекъсвач на веригата**— Проследява повреди на доставчик и автоматично отваря веригата при достигане на праг: -**ЗАТВОРЕНО**(здравословно) — Заявките протичат нормално -**OPEN**— Доставчикът е временно блокиран след повтарящи се повреди -**HALF_OPEN**— Тестване дали доставчикът се е възстановил + 3.**Прекъсвач на веригата**— Проследява повреди на доставчик и автоматично отваря веригата при достигане на праг: -**ЗАТВОРЕНО**(здравословно) — Заявките протичат нормално -**OPEN**— Доставчикът е временно блокиран след повтарящи се повреди -**HALF_OPEN**— Тестване дали доставчикът се е възстановил -4.**Правила и заключени идентификатори**— Показва състоянието на прекъсвача и заключените идентификатори с възможност за принудително отключване. + 4.**Правила и заключени идентификатори**— Показва състоянието на прекъсвача и заключените идентификатори с възможност за принудително отключване. -5.**Автоматично откриване на лимита на скоростта**— Наблюдава заглавките `429` и `Retry-After`, за да избегне проактивно достигане на лимитите на скоростта на доставчика. + 5.**Автоматично откриване на лимита на скоростта**— Наблюдава заглавките `429` и `Retry-After`, за да избегне проактивно достигане на лимитите на скоростта на доставчика. **Професионален съвет:**Използвайте бутона**Нулиране на всички**, за да изчистите всички прекъсвачи и изчаквания, когато доставчикът се възстанови от прекъсване.--- diff --git a/docs/i18n/bg/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/bg/docs/VM_DEPLOYMENT_GUIDE.md index 310bd1ad24..0e3bb4f9a4 100644 --- a/docs/i18n/bg/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/bg/docs/VM_DEPLOYMENT_GUIDE.md @@ -93,7 +93,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/cs/README.md b/docs/i18n/cs/README.md index 6271fb5271..e705c383a2 100644 --- a/docs/i18n/cs/README.md +++ b/docs/i18n/cs/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentace -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/cs/docs/ARCHITECTURE.md b/docs/i18n/cs/docs/ARCHITECTURE.md index 587e9fe20c..168b5281b5 100644 --- a/docs/i18n/cs/docs/ARCHITECTURE.md +++ b/docs/i18n/cs/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/cs/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/cs/docs/CODEBASE_DOCUMENTATION.md index 326ee2c5f6..f3bcc91f11 100644 --- a/docs/i18n/cs/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/cs/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**– hlavní streamovací kanál. Dva režimy: `TRANSLATE` (překlad plného formátu) a `PASSTHROUGH` (normalizovat + extrahovat použití). Zvládá ukládání do vyrovnávací paměti, odhad využití, sledování délky obsahu. Instance kodéru/dekodéru pro jednotlivé proudy se vyhýbají sdílenému stavu. | | `streamHelpers.ts` | Nízkoúrovňové nástroje SSE: `parseSSELine` (tolerující mezery), `hasValuableContent` (filtruje prázdné bloky pro OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (serializace SSE s ohledem na formát s vyčištěním `perf_metrics`). | | `usageTracking.ts` | Extrakce využití tokenů z libovolného formátu (Claude/OpenAI/Gemini/Responses), odhad pomocí samostatných poměrů znaků na token nástroje/zprávy, přidání do vyrovnávací paměti (bezpečnostní rezerva 2000 tokenů), filtrování polí podle formátu, protokolování konzoly pomocí barev ANSI. | -| `requestLogger.ts` | Protokolování požadavků na základě souborů (přihlášení přes `ENABLE_REQUEST_LOGS=true`). Vytváří složky relací s číslovanými soubory: `1_req_client.json` → `7_res_client.txt`. Všechny I/O jsou asynchronní (fire-and-forget). Maskuje citlivé hlavičky. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Zachycuje specifické vzory z Claude CLI (extrakce titulů, zahřívání, počet) a vrací falešné odpovědi bez volání jakéhokoli poskytovatele. Podporuje streamování i nestreamování. Záměrně omezeno na rozsah Claude CLI. | | `networkProxy.ts` | Vyřeší odchozí adresu URL proxy pro daného poskytovatele s prioritou: konfigurace specifická pro poskytovatele → globální konfigurace → proměnné prostředí (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Podporuje výjimky `NO_PROXY`. Konfiguraci mezipaměti po dobu 30 s. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/cs/docs/TROUBLESHOOTING.md b/docs/i18n/cs/docs/TROUBLESHOOTING.md index 8b2b5824f2..12097560e3 100644 --- a/docs/i18n/cs/docs/TROUBLESHOOTING.md +++ b/docs/i18n/cs/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/cs/docs/USER_GUIDE.md b/docs/i18n/cs/docs/USER_GUIDE.md index 41e2720a29..1cd09b5aab 100644 --- a/docs/i18n/cs/docs/USER_GUIDE.md +++ b/docs/i18n/cs/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | "nepravda" | Povolit Api Manager kopírovat úplné klíče API na vyžádání | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | "70" | Obnovovací kadence na straně serveru pro data o limitech poskytovatelů uložená v mezipaměti; Tlačítka pro obnovení uživatelského rozhraní stále spouštějí ruční synchronizaci | | `DISABLE_SQLITE_AUTO_BACKUP` | "nepravda" | Zakázat automatické snímky SQLite před zápisem/importem/obnovením; ruční zálohování stále funguje | -| `ENABLE_REQUEST_LOGS` | "nepravda" | Povolí protokoly požadavků/odpovědí | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | "nepravda" | Vynutit `Secure` auth cookie (za HTTPS reverzní proxy) | | `CLOUDFLARED_BIN` | odstaveno | Místo řízeného stahování použijte existující binární soubor `cloudflared` | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport pro spravované rychlé tunely (`http2`, `quic` nebo `auto`) | @@ -693,15 +693,15 @@ OmniRoute implementuje odolnost na úrovni poskytovatele se čtyřmi komponentam - Citlivost detekce rychlostního limitu - Exponenciální backoff parametry -2.**Upravitelné limity rychlosti**— Výchozí nastavení na úrovni systému konfigurovatelné na řídicím panelu: -**Požadavky za minutu (RPM)**– Maximální počet požadavků za minutu na účet -**Min Time Between Requests**— Minimální prodleva v milisekundách mezi požadavky -**Max Concurrent Requests**– Maximální počet souběžných požadavků na účet + 2.**Upravitelné limity rychlosti**— Výchozí nastavení na úrovni systému konfigurovatelné na řídicím panelu: -**Požadavky za minutu (RPM)**– Maximální počet požadavků za minutu na účet -**Min Time Between Requests**— Minimální prodleva v milisekundách mezi požadavky -**Max Concurrent Requests**– Maximální počet souběžných požadavků na účet - Klikněte na**Upravit**pro úpravu a poté na**Uložit**nebo**Zrušit**. Hodnoty přetrvávají prostřednictvím rozhraní API pro odolnost. -3.**Circuit Breaker**— Sleduje poruchy na poskytovatele a automaticky otevře okruh, když je dosaženo prahové hodnoty: -**UZAVŘENO**(Zdravé) – Požadavky běží normálně -**OPEN**— Poskytovatel je po opakovaných selháních dočasně zablokován -**HALF_OPEN**— Testování, zda se poskytovatel zotavil + 3.**Circuit Breaker**— Sleduje poruchy na poskytovatele a automaticky otevře okruh, když je dosaženo prahové hodnoty: -**UZAVŘENO**(Zdravé) – Požadavky běží normálně -**OPEN**— Poskytovatel je po opakovaných selháních dočasně zablokován -**HALF_OPEN**— Testování, zda se poskytovatel zotavil -4.**Policies & Locked Identifiers**– Zobrazuje stav jističe a uzamčené identifikátory s možností vynuceného odemknutí. + 4.**Policies & Locked Identifiers**– Zobrazuje stav jističe a uzamčené identifikátory s možností vynuceného odemknutí. -5.**Automatická detekce limitu rychlosti**— Monitoruje hlavičky `429` a `Retry-After`, aby se proaktivně zabránilo překročení limitů sazeb poskytovatele. + 5.**Automatická detekce limitu rychlosti**— Monitoruje hlavičky `429` a `Retry-After`, aby se proaktivně zabránilo překročení limitů sazeb poskytovatele. **Tip pro profesionály:**Když se poskytovatel zotaví z výpadku, použijte tlačítko**Resetovat vše**k vymazání všech jističů a ochlazení.--- diff --git a/docs/i18n/cs/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/cs/docs/VM_DEPLOYMENT_GUIDE.md index 8a03e9f510..239155f2f4 100644 --- a/docs/i18n/cs/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/cs/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/da/README.md b/docs/i18n/da/README.md index 06a0559457..eab1391fa4 100644 --- a/docs/i18n/da/README.md +++ b/docs/i18n/da/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentation -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/da/docs/ARCHITECTURE.md b/docs/i18n/da/docs/ARCHITECTURE.md index 5713fd9cd6..cba6d2c543 100644 --- a/docs/i18n/da/docs/ARCHITECTURE.md +++ b/docs/i18n/da/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/da/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/da/docs/CODEBASE_DOCUMENTATION.md index a6a04948d9..49f63862bb 100644 --- a/docs/i18n/da/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/da/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— den centrale streamingpipeline. To tilstande: 'OVERSÆTT' (oversættelse i fuld format) og 'PASSTHROUGH' (normalisere + udtræk brug). Håndterer chunk-buffring, brugsestimering, indholdslængdesporing. Per-stream encoder/decoder-instanser undgår delt tilstand. | | `streamHelpers.ts` | SSE-værktøjer på lavt niveau: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filtrerer tomme bidder til OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-bevidst SSE-serialisering med `perf_metrics`-oprydning). | | `usageTracking.ts` | Udtræk af tokenbrug fra ethvert format (Claude/OpenAI/Gemini/Responses), estimering med separate værktøj/meddelelse-char-per-token-forhold, buffertilsætning (2000 tokens sikkerhedsmargen), formatspecifik feltfiltrering, konsollogning med ANSI-farver. | -| `requestLogger.ts` | Filbaseret anmodningslogning (tilmelding via `ENABLE_REQUEST_LOGS=true`). Opretter sessionsmapper med nummererede filer: `1_req_client.json` → `7_res_client.txt`. Alle I/O er asynkrone (fire-and-forget). Masker følsomme overskrifter. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Opsnapper specifikke mønstre fra Claude CLI (titeludtræk, opvarmning, optælling) og returnerer falske svar uden at ringe til nogen udbyder. Understøtter både streaming og ikke-streaming. Med vilje begrænset til Claude CLI-omfang. | | `netværkProxy.ts` | Løser udgående proxy-URL for en given udbyder med forrang: udbyderspecifik konfiguration → global konfiguration → miljøvariabler (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Understøtter "NO_PROXY"-ekskluderinger. Caches konfiguration for 30'erne. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/da/docs/TROUBLESHOOTING.md b/docs/i18n/da/docs/TROUBLESHOOTING.md index 063677c844..c1e17f462f 100644 --- a/docs/i18n/da/docs/TROUBLESHOOTING.md +++ b/docs/i18n/da/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/da/docs/USER_GUIDE.md b/docs/i18n/da/docs/USER_GUIDE.md index b92c1dd1f2..63a424c639 100644 --- a/docs/i18n/da/docs/USER_GUIDE.md +++ b/docs/i18n/da/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | 'falsk' | Tillad Api Manager at kopiere hele API-nøgler efter behov | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Server-side opdateringskadence for cachelagrede Provider Limits-data; UI-opdateringsknapper udløser stadig manuel synkronisering | | `DISABLE_SQLITE_AUTO_BACKUP` | 'falsk' | Deaktiver automatiske SQLite-snapshots før skrivning/import/gendannelse; Manuelle sikkerhedskopier virker stadig | -| `ENABLE_REQUEST_LOGS` | 'falsk' | Aktiverer anmodnings-/svarlogs | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | 'falsk' | Tving 'Sikker' auth-cookie (bag HTTPS omvendt proxy) | | `CLOUDFLARED_BIN` | frakoblet | Brug en eksisterende `cloudflared` binær i stedet for administreret download | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport til administrerede hurtige tunneler (`http2`, `quic` eller `auto`) | @@ -692,15 +692,15 @@ OmniRoute implementerer modstandsdygtighed på udbyderniveau med fire komponente - Følsomhed for registrering af hastighedsgrænse - Eksponentielle backoff-parametre -2.**Redigerbare hastighedsgrænser**— Standardindstillinger på systemniveau, der kan konfigureres i dashboardet: -**Requests Per Minute (RPM)**— Maksimale anmodninger pr. minut pr. konto -**Min Time Between Requests**— Minimumsafstand i millisekunder mellem anmodninger -**Maksimal samtidige anmodninger**— Maksimalt antal samtidige anmodninger pr. konto + 2.**Redigerbare hastighedsgrænser**— Standardindstillinger på systemniveau, der kan konfigureres i dashboardet: -**Requests Per Minute (RPM)**— Maksimale anmodninger pr. minut pr. konto -**Min Time Between Requests**— Minimumsafstand i millisekunder mellem anmodninger -**Maksimal samtidige anmodninger**— Maksimalt antal samtidige anmodninger pr. konto - Klik på**Rediger**for at ændre, og klik derefter på**Gem**eller**Annuller**. Værdier bevarer via resilience API. -3.**Circuit Breaker**— Sporer fejl pr. udbyder og åbner automatisk kredsløbet, når en tærskel er nået: -**LUKKET**(Sund) — Anmodninger flyder normalt -**ÅBEN**— Udbyderen er midlertidigt blokeret efter gentagne fejl -**HALF_OPEN**— Tester, om udbyderen er genoprettet + 3.**Circuit Breaker**— Sporer fejl pr. udbyder og åbner automatisk kredsløbet, når en tærskel er nået: -**LUKKET**(Sund) — Anmodninger flyder normalt -**ÅBEN**— Udbyderen er midlertidigt blokeret efter gentagne fejl -**HALF_OPEN**— Tester, om udbyderen er genoprettet -4.**Politik og låste identifikatorer**— Viser strømafbryderstatus og låste identifikatorer med tvangsoplåsningsfunktion. + 4.**Politik og låste identifikatorer**— Viser strømafbryderstatus og låste identifikatorer med tvangsoplåsningsfunktion. -5.**Rate Limit Auto-Detection**— Overvåger "429" og "Retry-After"-headere for proaktivt at undgå at ramme udbyderens takstgrænser. + 5.**Rate Limit Auto-Detection**— Overvåger "429" og "Retry-After"-headere for proaktivt at undgå at ramme udbyderens takstgrænser. **Prof tip:**Brug knappen**Nulstil alle**til at rydde alle strømafbrydere og nedkøling, når en udbyder kommer sig efter en fejl.--- diff --git a/docs/i18n/da/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/da/docs/VM_DEPLOYMENT_GUIDE.md index 82000c23b9..583c4bb6df 100644 --- a/docs/i18n/da/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/da/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/de/README.md b/docs/i18n/de/README.md index 3019d440b4..0b2818ee98 100644 --- a/docs/i18n/de/README.md +++ b/docs/i18n/de/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentation -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/de/docs/ARCHITECTURE.md b/docs/i18n/de/docs/ARCHITECTURE.md index 807f2a4df7..d7e4d3e37a 100644 --- a/docs/i18n/de/docs/ARCHITECTURE.md +++ b/docs/i18n/de/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/de/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/de/docs/CODEBASE_DOCUMENTATION.md index 1f4d3b9f78..9f75e632a9 100644 --- a/docs/i18n/de/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/de/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**– die zentrale Streaming-Pipeline. Zwei Modi: „TRANSLATE“ (Vollformatübersetzung) und „PASSTHROUGH“ (Nutzung normalisieren + extrahieren). Verarbeitet Chunk-Pufferung, Nutzungsschätzung und Inhaltslängenverfolgung. Pro-Stream-Encoder-/Decoder-Instanzen vermeiden den gemeinsamen Status. | | `streamHelpers.ts` | Low-Level-SSE-Dienstprogramme: „parseSSELine“ (leerraumtolerant), „hasValuableContent“ (filtert leere Blöcke für OpenAI/Claude/Gemini), „fixInvalidId“, „formatSSE“ (formatbewusste SSE-Serialisierung mit „perf_metrics“-Bereinigung). | | `usageTracking.ts` | Extraktion der Token-Nutzung aus jedem Format (Claude/OpenAI/Gemini/Responses), Schätzung mit separaten Zeichen-pro-Token-Verhältnissen für Tools/Nachrichten, Pufferzugabe (2000 Token-Sicherheitsspielraum), formatspezifische Feldfilterung, Konsolenprotokollierung mit ANSI-Farben. | -| `requestLogger.ts` | Dateibasierte Anforderungsprotokollierung (Opt-in über „ENABLE_REQUEST_LOGS=true“). Erstellt Sitzungsordner mit nummerierten Dateien: „1_req_client.json“ → „7_res_client.txt“. Alle E/A erfolgen asynchron (Fire-and-Forget). Maskiert sensible Header. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Fängt bestimmte Muster von Claude CLI ab (Titelextraktion, Aufwärmen, Zählung) und gibt gefälschte Antworten zurück, ohne einen Anbieter anzurufen. Unterstützt sowohl Streaming als auch Nicht-Streaming. Absichtlich auf den Claude-CLI-Bereich beschränkt. | | `networkProxy.ts` | Löst die ausgehende Proxy-URL für einen bestimmten Anbieter mit der Priorität auf: anbieterspezifische Konfiguration → globale Konfiguration → Umgebungsvariablen („HTTPS_PROXY“/„HTTP_PROXY“/„ALL_PROXY“). Unterstützt „NO_PROXY“-Ausschlüsse. Speichert die Konfiguration 30 Sekunden lang im Cache. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/de/docs/TROUBLESHOOTING.md b/docs/i18n/de/docs/TROUBLESHOOTING.md index 8dfa2dffff..ff33ab3c13 100644 --- a/docs/i18n/de/docs/TROUBLESHOOTING.md +++ b/docs/i18n/de/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/de/docs/USER_GUIDE.md b/docs/i18n/de/docs/USER_GUIDE.md index 4193396229..45bfe29f67 100644 --- a/docs/i18n/de/docs/USER_GUIDE.md +++ b/docs/i18n/de/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | „falsch“ | Api Manager erlauben, bei Bedarf vollständige API-Schlüssel zu kopieren | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Serverseitige Aktualisierungsfrequenz für zwischengespeicherte Provider-Limit-Daten; Schaltflächen zum Aktualisieren der Benutzeroberfläche lösen weiterhin eine manuelle Synchronisierung aus | | `DISABLE_SQLITE_AUTO_BACKUP` | „falsch“ | Deaktivieren Sie automatische SQLite-Snapshots vor dem Schreiben/Importieren/Wiederherstellen. Manuelle Backups funktionieren weiterhin | -| `ENABLE_REQUEST_LOGS` | „falsch“ | Aktiviert Anforderungs-/Antwortprotokolle | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | „falsch“ | „Sicheres“ Authentifizierungs-Cookie erzwingen (hinter HTTPS-Reverse-Proxy) | | `CLOUDFLARED_BIN` | nicht gesetzt | Verwenden Sie eine vorhandene „Cloudflared“-Binärdatei anstelle eines verwalteten Downloads | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport für verwaltete Quick Tunnels („http2“, „quic“ oder „auto“) | @@ -693,15 +693,15 @@ OmniRoute implementiert Resilienz auf Anbieterebene mit vier Komponenten: - Empfindlichkeit der Grenzfrequenzerkennung - Exponentielle Backoff-Parameter -2.**Bearbeitbare Ratenbegrenzungen**– Standardeinstellungen auf Systemebene, konfigurierbar im Dashboard: -**Anfragen pro Minute (RPM)**– Maximale Anfragen pro Minute und Konto -**Min. Zeit zwischen Anfragen**– Mindestlücke in Millisekunden zwischen Anfragen -**Max. gleichzeitige Anfragen**– Maximale gleichzeitige Anfragen pro Konto + 2.**Bearbeitbare Ratenbegrenzungen**– Standardeinstellungen auf Systemebene, konfigurierbar im Dashboard: -**Anfragen pro Minute (RPM)**– Maximale Anfragen pro Minute und Konto -**Min. Zeit zwischen Anfragen**– Mindestlücke in Millisekunden zwischen Anfragen -**Max. gleichzeitige Anfragen**– Maximale gleichzeitige Anfragen pro Konto - Klicken Sie zum Ändern auf**Bearbeiten**und dann auf**Speichern**oder**Abbrechen**. Werte bleiben über die Resilience-API bestehen. -3.**Leistungsschalter**– Verfolgt Ausfälle pro Anbieter und öffnet automatisch den Stromkreis, wenn ein Schwellenwert erreicht wird: -**GESCHLOSSEN**(fehlerfrei) – Anfragen fließen normal -**OFFEN**– Der Anbieter ist nach wiederholten Ausfällen vorübergehend gesperrt -**HALF_OPEN**– Testen, ob sich der Anbieter erholt hat + 3.**Leistungsschalter**– Verfolgt Ausfälle pro Anbieter und öffnet automatisch den Stromkreis, wenn ein Schwellenwert erreicht wird: -**GESCHLOSSEN**(fehlerfrei) – Anfragen fließen normal -**OFFEN**– Der Anbieter ist nach wiederholten Ausfällen vorübergehend gesperrt -**HALF_OPEN**– Testen, ob sich der Anbieter erholt hat -4.**Richtlinien und Sperrkennungen**– Zeigt den Status des Leistungsschalters und die Sperrkennungen mit der Möglichkeit zum erzwungenen Entsperren an. + 4.**Richtlinien und Sperrkennungen**– Zeigt den Status des Leistungsschalters und die Sperrkennungen mit der Möglichkeit zum erzwungenen Entsperren an. -5.**Automatische Erkennung von Ratenbegrenzungen**– Überwacht die Header „429“ und „Retry-After“, um proaktiv zu vermeiden, dass die Ratenbegrenzungen der Anbieter erreicht werden. + 5.**Automatische Erkennung von Ratenbegrenzungen**– Überwacht die Header „429“ und „Retry-After“, um proaktiv zu vermeiden, dass die Ratenbegrenzungen der Anbieter erreicht werden. **Profi-Tipp:**Verwenden Sie die Schaltfläche**Alle zurücksetzen**, um alle Leistungsschalter und Abklingzeiten zu löschen, wenn ein Anbieter nach einem Ausfall wiederhergestellt wird.--- diff --git a/docs/i18n/de/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/de/docs/VM_DEPLOYMENT_GUIDE.md index 357dca1cde..f089b6ff4d 100644 --- a/docs/i18n/de/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/de/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/es/README.md b/docs/i18n/es/README.md index 47720abff4..6ccb053c9a 100644 --- a/docs/i18n/es/README.md +++ b/docs/i18n/es/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Documentación -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/es/docs/ARCHITECTURE.md b/docs/i18n/es/docs/ARCHITECTURE.md index 1783363207..7a3e3cc16b 100644 --- a/docs/i18n/es/docs/ARCHITECTURE.md +++ b/docs/i18n/es/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/es/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/es/docs/CODEBASE_DOCUMENTATION.md index 0e1f96f594..13001ce892 100644 --- a/docs/i18n/es/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/es/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `corriente.ts` | **SSE Transform Stream**: el canal principal de transmisión. Dos modos: `TRANSLATE` (traducción de formato completo) y `PASSTHROUGH` (normalizar + extraer uso). Maneja el almacenamiento en búfer de fragmentos, la estimación de uso y el seguimiento de la longitud del contenido. Las instancias de codificador/decodificador por flujo evitan el estado compartido. | | `streamHelpers.ts` | Utilidades SSE de bajo nivel: `parseSSELine` (tolerante a espacios en blanco), `hasValuableContent` (filtra fragmentos vacíos para OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (serialización SSE con reconocimiento de formato con limpieza `perf_metrics`). | | `usageTracking.ts` | Extracción de uso de tokens de cualquier formato (Claude/OpenAI/Gemini/Responses), estimación con proporciones separadas de caracteres por token de herramienta/mensaje, adición de búfer (margen de seguridad de 2000 tokens), filtrado de campos específicos del formato, registro de consola con colores ANSI. | -| `requestLogger.ts` | Registro de solicitudes basado en archivos (optar mediante `ENABLE_REQUEST_LOGS=true`). Crea carpetas de sesión con archivos numerados: `1_req_client.json` → `7_res_client.txt`. Todas las E/S son asíncronas (disparar y olvidar). Enmascara encabezados sensibles. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Intercepta patrones específicos de Claude CLI (extracción de títulos, calentamiento, recuento) y devuelve respuestas falsas sin llamar a ningún proveedor. Admite tanto streaming como no streaming. Limitado intencionalmente al alcance de Claude CLI. | | `redProxy.ts` | Resuelve la URL del proxy saliente para un proveedor determinado con prioridad: configuración específica del proveedor → configuración global → variables de entorno (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Admite exclusiones `NO_PROXY`. Configuración de cachés durante 30 segundos. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/es/docs/TROUBLESHOOTING.md b/docs/i18n/es/docs/TROUBLESHOOTING.md index 4e7d35330d..f61325ad93 100644 --- a/docs/i18n/es/docs/TROUBLESHOOTING.md +++ b/docs/i18n/es/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/es/docs/USER_GUIDE.md b/docs/i18n/es/docs/USER_GUIDE.md index 72aedeb485..2fe0718e49 100644 --- a/docs/i18n/es/docs/USER_GUIDE.md +++ b/docs/i18n/es/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `falso` | Permitir que Api Manager copie claves API completas a pedido | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Cadencia de actualización del lado del servidor para datos de límites de proveedor almacenados en caché; Los botones de actualización de la interfaz de usuario aún activan la sincronización manual | | `DISABLE_SQLITE_AUTO_BACKUP` | `falso` | Deshabilite las instantáneas automáticas de SQLite antes de escribir/importar/restaurar; las copias de seguridad manuales todavía funcionan | -| `ENABLE_REQUEST_LOGS` | `falso` | Habilita registros de solicitud/respuesta | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `falso` | Forzar cookie de autenticación "segura" (detrás del proxy inverso HTTPS) | | `CLOUDFLARED_BIN` | desarmado | Utilice un binario `cloudflared` existente en lugar de una descarga administrada | | `CLOUDFLARED_PROTOCOL` | `http2` | Transporte para Quick Tunnels administrados (`http2`, `quic` o `auto`) | @@ -692,15 +692,15 @@ OmniRoute implementa resiliencia a nivel de proveedor con cuatro componentes: - Sensibilidad de detección de límite de velocidad - Parámetros de retroceso exponencial -2.**Límites de tarifas editables**: valores predeterminados a nivel del sistema configurables en el panel: -**Solicitudes por minuto (RPM)**: solicitudes máximas por minuto por cuenta -**Tiempo mínimo entre solicitudes**: intervalo mínimo en milisegundos entre solicitudes -**Máximo de solicitudes simultáneas**: máximo de solicitudes simultáneas por cuenta + 2.**Límites de tarifas editables**: valores predeterminados a nivel del sistema configurables en el panel: -**Solicitudes por minuto (RPM)**: solicitudes máximas por minuto por cuenta -**Tiempo mínimo entre solicitudes**: intervalo mínimo en milisegundos entre solicitudes -**Máximo de solicitudes simultáneas**: máximo de solicitudes simultáneas por cuenta - Haga clic en**Editar**para modificar y luego en**Guardar**o**Cancelar**. Los valores persisten a través de la API de resiliencia. -3.**Disyuntor**: realiza un seguimiento de las fallas por proveedor y abre automáticamente el circuito cuando se alcanza un umbral: -**CERRADO**(En buen estado): las solicitudes fluyen normalmente -**ABIERTO**: el proveedor está bloqueado temporalmente después de fallas repetidas -**HALF_OPEN**— Probando si el proveedor se ha recuperado + 3.**Disyuntor**: realiza un seguimiento de las fallas por proveedor y abre automáticamente el circuito cuando se alcanza un umbral: -**CERRADO**(En buen estado): las solicitudes fluyen normalmente -**ABIERTO**: el proveedor está bloqueado temporalmente después de fallas repetidas -**HALF_OPEN**— Probando si el proveedor se ha recuperado -4.**Políticas e identificadores bloqueados**: muestra el estado del disyuntor y los identificadores bloqueados con capacidad de desbloqueo forzado. + 4.**Políticas e identificadores bloqueados**: muestra el estado del disyuntor y los identificadores bloqueados con capacidad de desbloqueo forzado. -5.**Detección automática del límite de tasa**: monitorea los encabezados "429" y "Reintentar después" para evitar de manera proactiva alcanzar los límites de tasa del proveedor. + 5.**Detección automática del límite de tasa**: monitorea los encabezados "429" y "Reintentar después" para evitar de manera proactiva alcanzar los límites de tasa del proveedor. **Consejo profesional:**Utilice el botón**Restablecer todo**para borrar todos los disyuntores y tiempos de reutilización cuando un proveedor se recupera de una interrupción.--- diff --git a/docs/i18n/es/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/es/docs/VM_DEPLOYMENT_GUIDE.md index 2cca72f586..dff3ad9e17 100644 --- a/docs/i18n/es/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/es/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/fi/README.md b/docs/i18n/fi/README.md index 411a4e1a61..7f476e6045 100644 --- a/docs/i18n/fi/README.md +++ b/docs/i18n/fi/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentaatio -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/fi/docs/ARCHITECTURE.md b/docs/i18n/fi/docs/ARCHITECTURE.md index 2b20d116ee..66bf43db46 100644 --- a/docs/i18n/fi/docs/ARCHITECTURE.md +++ b/docs/i18n/fi/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/fi/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/fi/docs/CODEBASE_DOCUMENTATION.md index 20b52be118..87d5ae5e60 100644 --- a/docs/i18n/fi/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/fi/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | "stream.ts" | **SSE Transform Stream**— suoratoiston ydinputki. Kaksi tilaa: `TRANSLATE` (täysmuotoinen käännös) ja `PASSTHROUGH` (normalisoi + poimi käyttö). Käsittelee osien puskuroinnin, käyttöarvioinnin ja sisällön pituuden seurannan. Virtakohtaiset enkooderi/dekooderiinstanssit välttävät jaetun tilan. | | `streamHelpers.ts` | Matalan tason SSE-apuohjelmat: "parseSSELine" (välilyöntejä sietävä), "hasValuableContent" (suodattaa tyhjät osat OpenAI:lle/Claudelle/Geminille), fixInvalidId, "formatSSE" (muototietoinen SSE-serialisointi ja "perf_metrics"). | | `usageTracking.ts` | Tokenin käytön poiminta mistä tahansa muodosta (Claude/OpenAI/Gemini/Responses), arvio erillisillä työkalu/viestin char-per-token-suhteilla, puskurin lisäys (2000 merkkiä turvamarginaali), muotokohtainen kenttäsuodatus, konsolin kirjaaminen ANSI-väreillä. | -| `requestLogger.ts` | Tiedostopohjainen pyyntöjen kirjaaminen (osallistu komennolla ENABLE_REQUEST_LOGS=true). Luo istuntokansioita numeroiduilla tiedostoilla: `1_req_client.json` → `7_res_client.txt`. Kaikki I/O on async (fire-and-forget). Peittää herkät otsikot. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Kaappaa tiettyjä malleja Claude CLI:stä (otsikon poimiminen, lämmittely, laskenta) ja palauttaa vääriä vastauksia soittamatta palveluntarjoajille. Tukee sekä suoratoistoa että ei-suoratoistoa. Tarkoituksella rajoitettu Claude CLI:n soveltamisalaan. | | `networkProxy.ts` | Ratkaisee tietyn palveluntarjoajan lähtevän välityspalvelimen URL-osoitteen etusijalla: palveluntarjoajakohtainen määritys → yleinen määritys → ympäristömuuttujat (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Tukee NO_PROXY-poikkeuksia. Välimuistin konfiguraatio 30 sekuntia. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/fi/docs/TROUBLESHOOTING.md b/docs/i18n/fi/docs/TROUBLESHOOTING.md index c2fbb68c02..5b74e4ab11 100644 --- a/docs/i18n/fi/docs/TROUBLESHOOTING.md +++ b/docs/i18n/fi/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/fi/docs/USER_GUIDE.md b/docs/i18n/fi/docs/USER_GUIDE.md index 29e6fbe908..f90f73d7fc 100644 --- a/docs/i18n/fi/docs/USER_GUIDE.md +++ b/docs/i18n/fi/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `väärä` | Salli Api Managerin kopioida täydet API-avaimet pyynnöstä | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES' | "70" | Palvelinpuolen päivitystiheys välimuistissa oleville palveluntarjoajan rajoitustiedoille; Käyttöliittymän päivityspainikkeet käynnistävät edelleen manuaalisen synkronoinnin | | `DISABLE_SQLITE_AUTO_BACKUP` | `väärä` | Poista automaattiset SQLite-vedoskuvat käytöstä ennen kirjoitusta/tuontia/palautusta; manuaaliset varmuuskopiot toimivat edelleen | -| `ENABLE_REQUEST_LOGS` | `väärä` | Ottaa käyttöön pyyntö-/vastauslokit | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `väärä` | Pakota "Suojattu" todennuseväste (HTTS:n käänteisen välityspalvelimen takana) | | "CLOUDFLARED_BIN" | pois käytöstä | Käytä olemassa olevaa "cloudflared"-binaaria hallitun latauksen sijasta | | `CLOUDFLARED_PROTOCOL' | `http2` | Kuljetus hallituille pikatunneleille ("http2", "quic" tai "auto") | @@ -691,15 +691,15 @@ OmniRoute toteuttaa toimittajatason joustavuutta neljällä osalla: - Nopeusrajan tunnistusherkkyys - Eksponentiaaliset peruutusparametrit -2.**Muokattavat nopeusrajoitukset**— Järjestelmätason oletusasetukset, jotka voidaan määrittää kojelaudassa: -**Pyynnöt minuutissa (RPM)**– Pyyntöjen enimmäismäärä minuutissa per tili -**Pyyntöjen välinen vähimmäisaika**- pyyntöjen välinen vähimmäisero millisekunteina -**Samanaikaisten pyyntöjen enimmäismäärä**— Samanaikaisten pyyntöjen enimmäismäärä tiliä kohden + 2.**Muokattavat nopeusrajoitukset**— Järjestelmätason oletusasetukset, jotka voidaan määrittää kojelaudassa: -**Pyynnöt minuutissa (RPM)**– Pyyntöjen enimmäismäärä minuutissa per tili -**Pyyntöjen välinen vähimmäisaika**- pyyntöjen välinen vähimmäisero millisekunteina -**Samanaikaisten pyyntöjen enimmäismäärä**— Samanaikaisten pyyntöjen enimmäismäärä tiliä kohden - Napsauta**Muokkaa**muokataksesi ja sitten**Tallenna**tai**Peruuta**. Arvot säilyvät resilience API:n kautta. -3.**Circuit Breaker**– Seuraa vikoja palveluntarjoajakohtaisesti ja avaa piirin automaattisesti, kun kynnys saavutetaan: -**SULJETTU**(terve) — Pyynnöt kulkevat normaalisti -**AUKI**— Palveluntarjoaja on tilapäisesti estetty toistuvien vikojen jälkeen -**HALF_OPEN**— Testataan, onko palveluntarjoaja palautunut + 3.**Circuit Breaker**– Seuraa vikoja palveluntarjoajakohtaisesti ja avaa piirin automaattisesti, kun kynnys saavutetaan: -**SULJETTU**(terve) — Pyynnöt kulkevat normaalisti -**AUKI**— Palveluntarjoaja on tilapäisesti estetty toistuvien vikojen jälkeen -**HALF_OPEN**— Testataan, onko palveluntarjoaja palautunut -4.**Policies & Locked Identifiers**— Näyttää katkaisijan tilan ja lukitut tunnisteet, joissa on pakko-avaaminen. + 4.**Policies & Locked Identifiers**— Näyttää katkaisijan tilan ja lukitut tunnisteet, joissa on pakko-avaaminen. -5.**Automaattinen nopeusrajoituksen tunnistus**— Valvoo "429"- ja "Retry-After"-otsikoita välttääkseen ennakoivasti palveluntarjoajan nopeusrajojen ylittymisen. + 5.**Automaattinen nopeusrajoituksen tunnistus**— Valvoo "429"- ja "Retry-After"-otsikoita välttääkseen ennakoivasti palveluntarjoajan nopeusrajojen ylittymisen. **Ammattilaisen vinkki:**Käytä**Nollaa kaikki**-painiketta tyhjentääksesi kaikki katkaisijat ja jäähdytykset, kun palveluntarjoaja toipuu katkosta.--- diff --git a/docs/i18n/fi/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/fi/docs/VM_DEPLOYMENT_GUIDE.md index f11ab08bee..58d3332b74 100644 --- a/docs/i18n/fi/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/fi/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/fr/README.md b/docs/i18n/fr/README.md index 362bdd077a..f153cfdd91 100644 --- a/docs/i18n/fr/README.md +++ b/docs/i18n/fr/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Documentation -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/fr/docs/ARCHITECTURE.md b/docs/i18n/fr/docs/ARCHITECTURE.md index a6d281af28..03aa026284 100644 --- a/docs/i18n/fr/docs/ARCHITECTURE.md +++ b/docs/i18n/fr/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/fr/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/fr/docs/CODEBASE_DOCUMENTATION.md index 1303c7b43f..ace29123b0 100644 --- a/docs/i18n/fr/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/fr/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream** : le pipeline de streaming principal. Deux modes : `TRANSLATE` (traduction plein format) et `PASSTHROUGH` (normaliser + extraire l'utilisation). Gère la mise en mémoire tampon des blocs, l'estimation de l'utilisation et le suivi de la longueur du contenu. Les instances d'encodeur/décodeur par flux évitent l'état partagé. | | `streamHelpers.ts` | Utilitaires SSE de bas niveau : `parseSSELine` (tolérant les espaces), `hasValuableContent` (filtre les morceaux vides pour OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (sérialisation SSE sensible au format avec nettoyage `perf_metrics`). | | `usageTracking.ts` | Extraction de l'utilisation des jetons à partir de n'importe quel format (Claude/OpenAI/Gemini/Responses), estimation avec des ratios outil/message séparés par jeton, ajout de tampon (marge de sécurité de 2000 jetons), filtrage de champs spécifiques au format, journalisation de la console avec couleurs ANSI. | -| `requestLogger.ts` | Journalisation des demandes basées sur des fichiers (opt-in via `ENABLE_REQUEST_LOGS=true`). Crée des dossiers de session avec des fichiers numérotés : `1_req_client.json` → `7_res_client.txt`. Toutes les E/S sont asynchrones (tirer et oublier). Masque les en-têtes sensibles. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Intercepte les modèles spécifiques de Claude CLI (extraction de titre, échauffement, décompte) et renvoie de fausses réponses sans appeler aucun fournisseur. Prend en charge le streaming et le non-streaming. Intentionnellement limité à la portée Claude CLI. | | `networkProxy.ts` | Résout l'URL du proxy sortant pour un fournisseur donné avec la priorité : configuration spécifique au fournisseur → configuration globale → variables d'environnement (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Prend en charge les exclusions `NO_PROXY`. Met en cache la configuration pendant 30 s. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/fr/docs/TROUBLESHOOTING.md b/docs/i18n/fr/docs/TROUBLESHOOTING.md index 219c35c693..c9ea3e8a7a 100644 --- a/docs/i18n/fr/docs/TROUBLESHOOTING.md +++ b/docs/i18n/fr/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/fr/docs/USER_GUIDE.md b/docs/i18n/fr/docs/USER_GUIDE.md index cb5f99b629..1bcc3e07c2 100644 --- a/docs/i18n/fr/docs/USER_GUIDE.md +++ b/docs/i18n/fr/docs/USER_GUIDE.md @@ -468,7 +468,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -500,7 +500,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `faux` | Autoriser Api Manager à copier des clés API complètes à la demande | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | '70' | Cadence d'actualisation côté serveur pour les données de limites du fournisseur mises en cache ; Les boutons d'actualisation de l'interface utilisateur déclenchent toujours la synchronisation manuelle | | `DISABLE_SQLITE_AUTO_BACKUP` | `faux` | Désactivez les instantanés SQLite automatiques avant les écritures/importations/restaurations ; les sauvegardes manuelles fonctionnent toujours | -| `ENABLE_REQUEST_LOGS` | `faux` | Active les journaux de requêtes/réponses | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `faux` | Forcer le cookie d'authentification « sécurisé » (derrière le proxy inverse HTTPS) | | `CLOUDFLARED_BIN` | non défini | Utiliser un binaire `cloudflared` existant au lieu d'un téléchargement géré | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport pour les tunnels rapides gérés (`http2`, `quic` ou `auto`) | @@ -693,15 +693,15 @@ OmniRoute met en œuvre la résilience au niveau du fournisseur avec quatre comp - Sensibilité de détection de limite de débit - Paramètres d'intervalle exponentiel -2.**Limites de débit modifiables**— Paramètres par défaut au niveau du système configurables dans le tableau de bord : -**Requêtes par minute (RPM)**— Nombre maximal de requêtes par minute et par compte -**Min Time Between Requests**— Écart minimum en millisecondes entre les requêtes -**Max Concurrent Requests**— Nombre maximal de requêtes simultanées par compte + 2.**Limites de débit modifiables**— Paramètres par défaut au niveau du système configurables dans le tableau de bord : -**Requêtes par minute (RPM)**— Nombre maximal de requêtes par minute et par compte -**Min Time Between Requests**— Écart minimum en millisecondes entre les requêtes -**Max Concurrent Requests**— Nombre maximal de requêtes simultanées par compte - Cliquez sur**Modifier**pour modifier, puis sur**Enregistrer**ou**Annuler**. Les valeurs persistent via l'API de résilience. -3.**Disjoncteur**— Suit les pannes par fournisseur et ouvre automatiquement le circuit lorsqu'un seuil est atteint : -**FERMÉ**(sain) — Les demandes circulent normalement -**OPEN**— Le fournisseur est temporairement bloqué après des échecs répétés -**HALF_OPEN**— Test si le fournisseur a récupéré + 3.**Disjoncteur**— Suit les pannes par fournisseur et ouvre automatiquement le circuit lorsqu'un seuil est atteint : -**FERMÉ**(sain) — Les demandes circulent normalement -**OPEN**— Le fournisseur est temporairement bloqué après des échecs répétés -**HALF_OPEN**— Test si le fournisseur a récupéré -4.**Politiques et identifiants verrouillés**— Affiche l'état du disjoncteur et les identifiants verrouillés avec capacité de déverrouillage forcé. + 4.**Politiques et identifiants verrouillés**— Affiche l'état du disjoncteur et les identifiants verrouillés avec capacité de déverrouillage forcé. -5.**Détection automatique des limites de débit**— Surveille les en-têtes « 429 » et « Retry-After » pour éviter de manière proactive d'atteindre les limites de débit du fournisseur. + 5.**Détection automatique des limites de débit**— Surveille les en-têtes « 429 » et « Retry-After » pour éviter de manière proactive d'atteindre les limites de débit du fournisseur. **Conseil de pro :**Utilisez le bouton**Réinitialiser tout**pour effacer tous les disjoncteurs et les temps de recharge lorsqu'un fournisseur se remet d'une panne.--- diff --git a/docs/i18n/fr/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/fr/docs/VM_DEPLOYMENT_GUIDE.md index 884b10d665..c6e0fc119a 100644 --- a/docs/i18n/fr/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/fr/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/he/README.md b/docs/i18n/he/README.md index 3c6c207268..15baf770bf 100644 --- a/docs/i18n/he/README.md +++ b/docs/i18n/he/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## תיעוד -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/he/docs/ARCHITECTURE.md b/docs/i18n/he/docs/ARCHITECTURE.md index 101c8aca35..108d63c1f1 100644 --- a/docs/i18n/he/docs/ARCHITECTURE.md +++ b/docs/i18n/he/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/he/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/he/docs/CODEBASE_DOCUMENTATION.md index 91a9a7eade..89ac11a843 100644 --- a/docs/i18n/he/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/he/docs/CODEBASE_DOCUMENTATION.md @@ -405,7 +405,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. | | `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). | | `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. | -| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. | | `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. | diff --git a/docs/i18n/he/docs/TROUBLESHOOTING.md b/docs/i18n/he/docs/TROUBLESHOOTING.md index f1f130ce04..8b497399a5 100644 --- a/docs/i18n/he/docs/TROUBLESHOOTING.md +++ b/docs/i18n/he/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/he/docs/USER_GUIDE.md b/docs/i18n/he/docs/USER_GUIDE.md index d1dbe36cf7..af8d74cf5a 100644 --- a/docs/i18n/he/docs/USER_GUIDE.md +++ b/docs/i18n/he/docs/USER_GUIDE.md @@ -493,7 +493,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -524,7 +524,7 @@ post_install() { | `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Server-side refresh cadence for cached Provider Limits data; UI refresh buttons still trigger manual sync | | `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work | -| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) | | `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport for managed Quick Tunnels (`http2`, `quic`, or `auto`) | diff --git a/docs/i18n/he/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/he/docs/VM_DEPLOYMENT_GUIDE.md index b6e082d5fa..c31121d3d3 100644 --- a/docs/i18n/he/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/he/docs/VM_DEPLOYMENT_GUIDE.md @@ -108,7 +108,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/hi/README.md b/docs/i18n/hi/README.md index bd6ee203d5..ddb8df27a1 100644 --- a/docs/i18n/hi/README.md +++ b/docs/i18n/hi/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## दस्तावेज़ -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/hi/docs/ARCHITECTURE.md b/docs/i18n/hi/docs/ARCHITECTURE.md index adb69b5ed7..3d83046780 100644 --- a/docs/i18n/hi/docs/ARCHITECTURE.md +++ b/docs/i18n/hi/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/hi/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/hi/docs/CODEBASE_DOCUMENTATION.md index 72507e2784..1cd05fd919 100644 --- a/docs/i18n/hi/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/hi/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **एसएसई ट्रांसफॉर्म स्ट्रीम**- कोर स्ट्रीमिंग पाइपलाइन। दो मोड: `अनुवाद` (पूर्ण प्रारूप अनुवाद) और `पासथ्रू` (सामान्यीकृत + उपयोग निकालें)। चंक बफ़रिंग, उपयोग अनुमान, सामग्री लंबाई ट्रैकिंग को संभालता है। प्रति-स्ट्रीम एनकोडर/डिकोडर उदाहरण साझा स्थिति से बचते हैं। | | `streamHelpers.ts` | निम्न-स्तरीय SSE उपयोगिताएँ: `parseSSELine` (व्हाट्सएप-टॉलरेंट), `hasValuableContent` (OpenAI/Claude/Gemini के लिए खाली हिस्सों को फ़िल्टर करता है), `fixInvalidId`, `formatSSE` (`perf_metrics` क्लीनअप के साथ प्रारूप-जागरूक SSE क्रमबद्धता)। | | `useTracking.ts` | किसी भी प्रारूप से टोकन उपयोग निष्कर्षण (क्लाउड/ओपनएआई/मिथुन/प्रतिक्रियाएं), अलग टूल/संदेश चार-प्रति-टोकन अनुपात के साथ अनुमान, बफर जोड़ (2000 टोकन सुरक्षा मार्जिन), प्रारूप-विशिष्ट फ़ील्ड फ़िल्टरिंग, एएनएसआई रंगों के साथ कंसोल लॉगिंग। | -| `requestLogger.ts` | फ़ाइल-आधारित अनुरोध लॉगिंग (`ENABLE_REQUEST_LOGS=true` के माध्यम से ऑप्ट-इन करें)। क्रमांकित फ़ाइलों के साथ सत्र फ़ोल्डर बनाता है: `1_req_client.json` → `7_res_client.txt`। सभी I/O async (दाग-और-भूल) है। संवेदनशील हेडर को छुपाता है. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | क्लाउड सीएलआई (शीर्षक निष्कर्षण, वार्मअप, गिनती) से विशिष्ट पैटर्न को रोकता है और किसी भी प्रदाता को कॉल किए बिना नकली प्रतिक्रियाएं लौटाता है। स्ट्रीमिंग और नॉन-स्ट्रीमिंग दोनों का समर्थन करता है। जानबूझकर क्लाउड सीएलआई दायरे तक सीमित। | | `networkProxy.ts` | किसी दिए गए प्रदाता के लिए आउटबाउंड प्रॉक्सी URL को प्राथमिकता के साथ हल करता है: प्रदाता-विशिष्ट कॉन्फ़िगरेशन → वैश्विक कॉन्फ़िगरेशन → पर्यावरण चर (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`)। `NO_PROXY` बहिष्करण का समर्थन करता है। 30 के दशक के लिए कैश कॉन्फिगरेशन। | #### SSE Streaming Pipeline | diff --git a/docs/i18n/hi/docs/TROUBLESHOOTING.md b/docs/i18n/hi/docs/TROUBLESHOOTING.md index 5fb25a9ebb..e7f376865a 100644 --- a/docs/i18n/hi/docs/TROUBLESHOOTING.md +++ b/docs/i18n/hi/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/hi/docs/USER_GUIDE.md b/docs/i18n/hi/docs/USER_GUIDE.md index 96de8079ff..169b832144 100644 --- a/docs/i18n/hi/docs/USER_GUIDE.md +++ b/docs/i18n/hi/docs/USER_GUIDE.md @@ -469,7 +469,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -501,7 +501,7 @@ vlicense LICENSE | `अनुमति_एपीआई_कुंजी_प्रकटीकरण` | 'झूठा' | एपीआई प्रबंधक को मांग पर पूर्ण एपीआई कुंजियाँ कॉपी करने की अनुमति दें | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | कैश्ड प्रदाता सीमा डेटा के लिए सर्वर-साइड ताज़ा ताल; यूआई रीफ्रेश बटन अभी भी मैन्युअल सिंक ट्रिगर करते हैं | | `DISABLE_SQLITE_AUTO_BACKUP` | 'झूठा' | लिखने/आयात/पुनर्स्थापित करने से पहले स्वचालित SQLite स्नैपशॉट अक्षम करें; मैन्युअल बैकअप अभी भी काम करते हैं | -| `ENABLE_REQUEST_LOGS` | 'झूठा' | अनुरोध/प्रतिक्रिया लॉग सक्षम करता है | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | 'झूठा' | `सिक्योर` ऑथ कुकी को बाध्य करें (एचटीटीपीएस रिवर्स प्रॉक्सी के पीछे) | | `CLOUDFLARED_BIN` | परेशान | प्रबंधित डाउनलोड के बजाय मौजूदा `क्लाउडफ्लेयर्ड` बाइनरी का उपयोग करें | `क्लाउडफ्लेयर्ड_प्रोटोकॉल` | `http2` | प्रबंधित त्वरित सुरंगों के लिए परिवहन ('http2', 'त्वरित', या 'ऑटो') | @@ -693,15 +693,15 @@ Chain: production-fallback - दर सीमा का पता लगाने की संवेदनशीलता - घातीय बैकऑफ़ पैरामीटर -2.**संपादन योग्य दर सीमाएँ**— डैशबोर्ड में कॉन्फ़िगर करने योग्य सिस्टम-स्तरीय डिफ़ॉल्ट: -**प्रति मिनट अनुरोध (आरपीएम)**- प्रति खाता प्रति मिनट अधिकतम अनुरोध -**अनुरोधों के बीच न्यूनतम समय**- अनुरोधों के बीच मिलीसेकंड में न्यूनतम अंतर -**अधिकतम समवर्ती अनुरोध**— प्रति खाता अधिकतम एक साथ अनुरोध + 2.**संपादन योग्य दर सीमाएँ**— डैशबोर्ड में कॉन्फ़िगर करने योग्य सिस्टम-स्तरीय डिफ़ॉल्ट: -**प्रति मिनट अनुरोध (आरपीएम)**- प्रति खाता प्रति मिनट अधिकतम अनुरोध -**अनुरोधों के बीच न्यूनतम समय**- अनुरोधों के बीच मिलीसेकंड में न्यूनतम अंतर -**अधिकतम समवर्ती अनुरोध**— प्रति खाता अधिकतम एक साथ अनुरोध - संशोधित करने के लिए**संपादित करें**पर क्लिक करें, फिर**सहेजें**या**रद्द करें**पर क्लिक करें। मान लचीलापन एपीआई के माध्यम से बने रहते हैं। -3.**सर्किट ब्रेकर**- प्रति प्रदाता विफलताओं को ट्रैक करता है और सीमा तक पहुंचने पर स्वचालित रूप से सर्किट खोलता है: -**बंद**(स्वस्थ) - अनुरोध सामान्य रूप से प्रवाहित होते हैं -**खुला**- बार-बार विफलताओं के बाद प्रदाता अस्थायी रूप से अवरुद्ध हो जाता है -**आधा_खुला**— परीक्षण किया जा रहा है कि प्रदाता ठीक हो गया है या नहीं + 3.**सर्किट ब्रेकर**- प्रति प्रदाता विफलताओं को ट्रैक करता है और सीमा तक पहुंचने पर स्वचालित रूप से सर्किट खोलता है: -**बंद**(स्वस्थ) - अनुरोध सामान्य रूप से प्रवाहित होते हैं -**खुला**- बार-बार विफलताओं के बाद प्रदाता अस्थायी रूप से अवरुद्ध हो जाता है -**आधा_खुला**— परीक्षण किया जा रहा है कि प्रदाता ठीक हो गया है या नहीं -4.**नीतियाँ और लॉक किए गए पहचानकर्ता**- बल-अनलॉक क्षमता के साथ सर्किट ब्रेकर की स्थिति और लॉक किए गए पहचानकर्ताओं को दिखाता है। + 4.**नीतियाँ और लॉक किए गए पहचानकर्ता**- बल-अनलॉक क्षमता के साथ सर्किट ब्रेकर की स्थिति और लॉक किए गए पहचानकर्ताओं को दिखाता है। -5.**दर सीमा ऑटो-डिटेक्शन**- प्रदाता दर सीमा से बचने के लिए सक्रिय रूप से `429` और `पुनः प्रयास करें` हेडर पर नज़र रखता है। + 5.**दर सीमा ऑटो-डिटेक्शन**- प्रदाता दर सीमा से बचने के लिए सक्रिय रूप से `429` और `पुनः प्रयास करें` हेडर पर नज़र रखता है। **प्रो टिप:**जब कोई प्रदाता आउटेज से उबरता है तो सभी सर्किट ब्रेकर और कूलडाउन को साफ़ करने के लिए**रीसेट ऑल**बटन का उपयोग करें।--- diff --git a/docs/i18n/hi/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/hi/docs/VM_DEPLOYMENT_GUIDE.md index f2dccb5e75..93d394be32 100644 --- a/docs/i18n/hi/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/hi/docs/VM_DEPLOYMENT_GUIDE.md @@ -99,7 +99,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/hu/README.md b/docs/i18n/hu/README.md index 88e3f44d8e..d8bf7e1042 100644 --- a/docs/i18n/hu/README.md +++ b/docs/i18n/hu/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentáció -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/hu/docs/ARCHITECTURE.md b/docs/i18n/hu/docs/ARCHITECTURE.md index aab37b02ed..7bc4a1a2e8 100644 --- a/docs/i18n/hu/docs/ARCHITECTURE.md +++ b/docs/i18n/hu/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/hu/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/hu/docs/CODEBASE_DOCUMENTATION.md index 7f8037030b..1cbabb9fe6 100644 --- a/docs/i18n/hu/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/hu/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `folyam.ts` | **SSE Transform Stream**– a mag adatfolyam-folyamat. Két mód: „TRANSLATE” (teljes formátumú fordítás) és „PASSTHROUGH” (használat normalizálása + kivonat). Kezeli a darabok pufferelését, a felhasználás becslését, a tartalom hosszának követését. A folyamonkénti kódoló/dekódoló példányok elkerülik a megosztott állapotot. | | `streamHelpers.ts` | Alacsony szintű SSE-segédprogramok: `parseSSELine` (szóköztűrő), `hasValuableContent` (üres darabokat szűr az OpenAI/Claude/Gemini számára), `fixInvalidId`, `formatSSE` (formátum-tudatos SSE szerializálás a `perf_metrics` paraméterrel). | | `usageTracking.ts` | Tokenhasználati kinyerés bármilyen formátumból (Claude/OpenAI/Gemini/Responses), becslés külön eszköz/üzenet char-per-token arányokkal, puffer hozzáadása (2000 token biztonsági ráhagyás), formátum-specifikus mezőszűrés, konzolnaplózás ANSI színekkel. | -| `requestLogger.ts` | Fájlalapú kérések naplózása (feliratkozás az `ENABLE_REQUEST_LOGS=true' paraméterrel). Munkamenet-mappákat hoz létre számozott fájlokkal: `1_req_client.json`→`7_res_client.txt`. Minden I/O aszinkron (gyújt és felejt). Elfedi az érzékeny fejléceket. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Elfogja a Claude CLI meghatározott mintáit (címkivonás, bemelegítés, számlálás), és hamis válaszokat ad vissza anélkül, hogy bármelyik szolgáltatót is felhívná. Támogatja a streaminget és a nem adatfolyamot egyaránt. Szándékosan a Claude CLI hatókörére korlátozva. | | `networkProxy.ts` | Feloldja egy adott szolgáltató kimenő proxy URL-jét elsőbbséggel: szolgáltató-specifikus konfiguráció → globális konfiguráció → környezeti változók (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Támogatja a „NO_PROXY” kizárásokat. Gyorsítótár konfiguráció 30 másodpercig. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/hu/docs/TROUBLESHOOTING.md b/docs/i18n/hu/docs/TROUBLESHOOTING.md index 6719ac515a..16e5214b08 100644 --- a/docs/i18n/hu/docs/TROUBLESHOOTING.md +++ b/docs/i18n/hu/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/hu/docs/USER_GUIDE.md b/docs/i18n/hu/docs/USER_GUIDE.md index beb8630c79..dfb3212ebe 100644 --- a/docs/i18n/hu/docs/USER_GUIDE.md +++ b/docs/i18n/hu/docs/USER_GUIDE.md @@ -468,7 +468,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -500,7 +500,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | "hamis" | Engedélyezze az Api Managernek a teljes API-kulcsok igény szerinti másolását | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | "70" | Szerveroldali frissítési ütem a gyorsítótárazott szolgáltatói korlátok adataihoz; A felhasználói felület frissítő gombjai továbbra is kézi szinkronizálást indítanak el | | `DISABLE_SQLITE_AUTO_BACKUP` | "hamis" | Az automatikus SQLite pillanatképek letiltása az írás/importálás/visszaállítás előtt; a kézi biztonsági mentések továbbra is működnek | -| `ENABLE_REQUEST_LOGS` | "hamis" | Engedélyezi a kérés/válasz naplózást | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE' | "hamis" | "Biztonságos" hitelesítési cookie kényszerítése (a HTTPS fordított proxy mögött) | | `CLOUDFLARED_BIN` | beállítva | A felügyelt letöltés helyett használjon egy létező 'cloudflared' bináris fájlt | | `CLOUDFLARED_PROTOCOL` | `http2` | Felügyelt gyorsalagutak szállítása ("http2", "quic" vagy "auto") | @@ -693,15 +693,15 @@ Az OmniRoute szolgáltatói szintű rugalmasságot valósít meg négy összetev - Sebességkorlát érzékelési érzékenység - Exponenciális backoff paraméterek -2.**Szerkeszthető díjkorlátok**— Az irányítópulton konfigurálható rendszerszintű alapértékek: -**Percenkénti kérések (RPM)**– A percenkénti kérések száma fiókonként -**Minimális idő a kérések között**- Minimális eltérés ezredmásodpercben a kérések között -**Maximális egyidejű kérések**- Maximális egyidejű kérések száma fiókonként + 2.**Szerkeszthető díjkorlátok**— Az irányítópulton konfigurálható rendszerszintű alapértékek: -**Percenkénti kérések (RPM)**– A percenkénti kérések száma fiókonként -**Minimális idő a kérések között**- Minimális eltérés ezredmásodpercben a kérések között -**Maximális egyidejű kérések**- Maximális egyidejű kérések száma fiókonként - Kattintson a**Szerkesztés**gombra a módosításhoz, majd a**Mentés**vagy a**Mégse**gombra. Az értékek a rezilience API-n keresztül megmaradnak. -3.**Circuit Breaker**– Nyomon követi a hibákat szolgáltatónként, és automatikusan megnyitja az áramkört egy küszöbérték elérésekor: -**ZÁRVA**(egészséges) – A kérések normálisan futnak -**NYITVA**— A szolgáltató ideiglenesen blokkolva van ismétlődő hibák után -**HALF_OPEN**— Tesztelés, hogy a szolgáltató helyreállt-e + 3.**Circuit Breaker**– Nyomon követi a hibákat szolgáltatónként, és automatikusan megnyitja az áramkört egy küszöbérték elérésekor: -**ZÁRVA**(egészséges) – A kérések normálisan futnak -**NYITVA**— A szolgáltató ideiglenesen blokkolva van ismétlődő hibák után -**HALF_OPEN**— Tesztelés, hogy a szolgáltató helyreállt-e -4.**Policies & Locked Identifiers**— Megjeleníti a megszakító állapotát és a zárolt azonosítókat kényszer-feloldási képességgel. + 4.**Policies & Locked Identifiers**— Megjeleníti a megszakító állapotát és a zárolt azonosítókat kényszer-feloldási képességgel. -5.**Automatikus díjkorlát-észlelés**– Figyeli a "429" és az "Újrapróbálkozás után" fejléceket, hogy proaktívan elkerülje a szolgáltatói díjkorlátok átlépését. + 5.**Automatikus díjkorlát-észlelés**– Figyeli a "429" és az "Újrapróbálkozás után" fejléceket, hogy proaktívan elkerülje a szolgáltatói díjkorlátok átlépését. **Profi tipp:**Használja a**Reset All**gombot az összes megszakító és leállás törléséhez, amikor a szolgáltató felépül egy kiesésből.--- diff --git a/docs/i18n/hu/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/hu/docs/VM_DEPLOYMENT_GUIDE.md index 5cfdd8edbd..cf1feafb10 100644 --- a/docs/i18n/hu/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/hu/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/id/README.md b/docs/i18n/id/README.md index aed0df12fb..166a33535f 100644 --- a/docs/i18n/id/README.md +++ b/docs/i18n/id/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentasi -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/id/docs/ARCHITECTURE.md b/docs/i18n/id/docs/ARCHITECTURE.md index 99420b9f46..fb209ee3aa 100644 --- a/docs/i18n/id/docs/ARCHITECTURE.md +++ b/docs/i18n/id/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/id/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/id/docs/CODEBASE_DOCUMENTATION.md index a40a6b0916..2ac34a51d0 100644 --- a/docs/i18n/id/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/id/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— saluran streaming inti. Dua mode: `TRANSLATE` (terjemahan format penuh) dan `PASSTHROUGH` (menormalkan + mengekstrak penggunaan). Menangani buffering potongan, estimasi penggunaan, pelacakan panjang konten. Instance encoder/decoder per-aliran menghindari status bersama. | | `streamHelpers.ts` | Utilitas SSE tingkat rendah: `parseSSELine` (toleran spasi), `hasValuableContent` (memfilter potongan kosong untuk OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (serialisasi SSE yang mendukung format dengan pembersihan `perf_metrics`). | | `usageTracking.ts` | Ekstraksi penggunaan token dari format apa pun (Claude/OpenAI/Gemini/Responses), estimasi dengan rasio karakter per token alat/pesan terpisah, penambahan buffer (margin keamanan token 2000), pemfilteran bidang khusus format, logging konsol dengan warna ANSI. | -| `requestLogger.ts` | Pencatatan permintaan berbasis file (ikut serta melalui `ENABLE_REQUEST_LOGS=true`). Membuat folder sesi dengan file bernomor: `1_req_client.json` → `7_res_client.txt`. Semua I/O bersifat asinkron (api-dan-lupakan). Menutupi header sensitif. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Mencegat pola tertentu dari Claude CLI (ekstraksi judul, pemanasan, penghitungan) dan mengembalikan respons palsu tanpa menghubungi penyedia mana pun. Mendukung streaming dan non-streaming. Sengaja dibatasi pada scope Claude CLI. | | `networkProxy.ts` | Menyelesaikan URL proksi keluar untuk penyedia tertentu dengan prioritas: konfigurasi khusus penyedia → konfigurasi global → variabel lingkungan (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Mendukung pengecualian `NO_PROXY`. Konfigurasi cache selama 30 detik. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/id/docs/TROUBLESHOOTING.md b/docs/i18n/id/docs/TROUBLESHOOTING.md index e631f0b0c2..37122a124a 100644 --- a/docs/i18n/id/docs/TROUBLESHOOTING.md +++ b/docs/i18n/id/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/id/docs/USER_GUIDE.md b/docs/i18n/id/docs/USER_GUIDE.md index 42209158bb..1933bc4446 100644 --- a/docs/i18n/id/docs/USER_GUIDE.md +++ b/docs/i18n/id/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `salah` | Izinkan Api Manager menyalin kunci API lengkap sesuai permintaan | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Irama penyegaran sisi server untuk data Batas Penyedia yang di-cache; Tombol penyegaran UI masih memicu sinkronisasi manual | | `DISABLE_SQLITE_AUTO_BACKUP` | `salah` | Nonaktifkan snapshot SQLite otomatis sebelum menulis/impor/pulihkan; backup manual masih berfungsi | -| `ENABLE_REQUEST_LOGS` | `salah` | Mengaktifkan log permintaan/respons | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `salah` | Paksa cookie autentikasi `Aman` (di belakang proksi terbalik HTTPS) | | `CLOUDFLARED_BIN` | tidak disetel | Gunakan biner `cloudflared` yang sudah ada alih-alih unduhan terkelola | | `CLOUDFLARED_PROTOCOL` | `http2` | Transportasi untuk Terowongan Cepat terkelola (`http2`, `quic`, atau `auto`) | @@ -692,15 +692,15 @@ OmniRoute mengimplementasikan ketahanan tingkat penyedia dengan empat komponen: - Sensitivitas deteksi batas kecepatan - Parameter backoff eksponensial -2.**Batas Tarif yang Dapat Diedit**— Default tingkat sistem dapat dikonfigurasi di dasbor: -**Permintaan Per Menit (RPM)**— Permintaan maksimum per menit per akun -**Waktu Minimum Antar Permintaan**— Kesenjangan minimum dalam milidetik antar permintaan -**Permintaan Bersamaan Maksimum**— Permintaan simultan maksimum per akun + 2.**Batas Tarif yang Dapat Diedit**— Default tingkat sistem dapat dikonfigurasi di dasbor: -**Permintaan Per Menit (RPM)**— Permintaan maksimum per menit per akun -**Waktu Minimum Antar Permintaan**— Kesenjangan minimum dalam milidetik antar permintaan -**Permintaan Bersamaan Maksimum**— Permintaan simultan maksimum per akun - Klik**Edit**untuk mengubah, lalu**Simpan**atau**Batal**. Nilai-nilai bertahan melalui API ketahanan. -3.**Pemutus Sirkuit**— Melacak kegagalan per penyedia dan secara otomatis membuka sirkuit ketika ambang batas tercapai: -**TUTUP**(Sehat) — Permintaan mengalir normal -**BUKA**— Penyedia diblokir sementara setelah kegagalan berulang kali -**HALF_OPEN**— Menguji apakah penyedia telah pulih + 3.**Pemutus Sirkuit**— Melacak kegagalan per penyedia dan secara otomatis membuka sirkuit ketika ambang batas tercapai: -**TUTUP**(Sehat) — Permintaan mengalir normal -**BUKA**— Penyedia diblokir sementara setelah kegagalan berulang kali -**HALF_OPEN**— Menguji apakah penyedia telah pulih -4.**Kebijakan & Pengidentifikasi Terkunci**— Menampilkan status pemutus sirkuit dan pengidentifikasi terkunci dengan kemampuan buka paksa. + 4.**Kebijakan & Pengidentifikasi Terkunci**— Menampilkan status pemutus sirkuit dan pengidentifikasi terkunci dengan kemampuan buka paksa. -5.**Deteksi Otomatis Batas Kecepatan**— Memantau header `429` dan `Coba Ulang-Setelah` untuk secara proaktif menghindari batas kecepatan penyedia. + 5.**Deteksi Otomatis Batas Kecepatan**— Memantau header `429` dan `Coba Ulang-Setelah` untuk secara proaktif menghindari batas kecepatan penyedia. **Kiat Pro:**Gunakan tombol**Reset Semua**untuk menghapus semua pemutus sirkuit dan cooldown saat penyedia pulih dari pemadaman listrik.--- diff --git a/docs/i18n/id/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/id/docs/VM_DEPLOYMENT_GUIDE.md index dd22f9506f..34e5fb1910 100644 --- a/docs/i18n/id/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/id/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/in/README.md b/docs/i18n/in/README.md index d38dcdb52d..a993b833b7 100644 --- a/docs/i18n/in/README.md +++ b/docs/i18n/in/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## दस्तावेज़ -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/in/docs/ARCHITECTURE.md b/docs/i18n/in/docs/ARCHITECTURE.md index b98e57fd7f..cd42a8288e 100644 --- a/docs/i18n/in/docs/ARCHITECTURE.md +++ b/docs/i18n/in/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/in/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/in/docs/CODEBASE_DOCUMENTATION.md index 46ab42485a..14cd4b1492 100644 --- a/docs/i18n/in/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/in/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **एसएसई ट्रांसफॉर्म स्ट्रीम**- कोर स्ट्रीमिंग पाइपलाइन। दो मोड: `अनुवाद` (पूर्ण प्रारूप अनुवाद) और `पासथ्रू` (सामान्यीकृत + उपयोग निकालें)। चंक बफ़रिंग, उपयोग अनुमान, सामग्री लंबाई ट्रैकिंग को संभालता है। प्रति-स्ट्रीम एनकोडर/डिकोडर उदाहरण साझा स्थिति से बचते हैं। | | `streamHelpers.ts` | निम्न-स्तरीय SSE उपयोगिताएँ: `parseSSELine` (व्हाट्सएप-टॉलरेंट), `hasValuableContent` (OpenAI/Claude/Gemini के लिए खाली हिस्सों को फ़िल्टर करता है), `fixInvalidId`, `formatSSE` (`perf_metrics` क्लीनअप के साथ प्रारूप-जागरूक SSE क्रमबद्धता)। | | `useTracking.ts` | किसी भी प्रारूप से टोकन उपयोग निष्कर्षण (क्लाउड/ओपनएआई/मिथुन/प्रतिक्रियाएं), अलग टूल/संदेश चार-प्रति-टोकन अनुपात के साथ अनुमान, बफर जोड़ (2000 टोकन सुरक्षा मार्जिन), प्रारूप-विशिष्ट फ़ील्ड फ़िल्टरिंग, एएनएसआई रंगों के साथ कंसोल लॉगिंग। | -| `requestLogger.ts` | फ़ाइल-आधारित अनुरोध लॉगिंग (`ENABLE_REQUEST_LOGS=true` के माध्यम से ऑप्ट-इन करें)। क्रमांकित फ़ाइलों के साथ सत्र फ़ोल्डर बनाता है: `1_req_client.json` → `7_res_client.txt`। सभी I/O async (दाग-और-भूल) है। संवेदनशील हेडर को छुपाता है. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | क्लाउड सीएलआई (शीर्षक निष्कर्षण, वार्मअप, गिनती) से विशिष्ट पैटर्न को रोकता है और किसी भी प्रदाता को कॉल किए बिना नकली प्रतिक्रियाएं लौटाता है। स्ट्रीमिंग और नॉन-स्ट्रीमिंग दोनों का समर्थन करता है। जानबूझकर क्लाउड सीएलआई दायरे तक सीमित। | | `networkProxy.ts` | किसी दिए गए प्रदाता के लिए आउटबाउंड प्रॉक्सी URL को प्राथमिकता के साथ हल करता है: प्रदाता-विशिष्ट कॉन्फ़िगरेशन → वैश्विक कॉन्फ़िगरेशन → पर्यावरण चर (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`)। `NO_PROXY` बहिष्करण का समर्थन करता है। 30 के दशक के लिए कैश कॉन्फिगरेशन। | #### SSE Streaming Pipeline | diff --git a/docs/i18n/in/docs/TROUBLESHOOTING.md b/docs/i18n/in/docs/TROUBLESHOOTING.md index de6109cf64..00a4bc1983 100644 --- a/docs/i18n/in/docs/TROUBLESHOOTING.md +++ b/docs/i18n/in/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/in/docs/USER_GUIDE.md b/docs/i18n/in/docs/USER_GUIDE.md index a2b4e286c2..86b3037f4d 100644 --- a/docs/i18n/in/docs/USER_GUIDE.md +++ b/docs/i18n/in/docs/USER_GUIDE.md @@ -469,7 +469,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -501,7 +501,7 @@ vlicense LICENSE | `अनुमति_एपीआई_कुंजी_प्रकटीकरण` | 'झूठा' | एपीआई प्रबंधक को मांग पर पूर्ण एपीआई कुंजियाँ कॉपी करने की अनुमति दें | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | कैश्ड प्रदाता सीमा डेटा के लिए सर्वर-साइड ताज़ा ताल; यूआई रीफ्रेश बटन अभी भी मैन्युअल सिंक ट्रिगर करते हैं | | `DISABLE_SQLITE_AUTO_BACKUP` | 'झूठा' | लिखने/आयात/पुनर्स्थापित करने से पहले स्वचालित SQLite स्नैपशॉट अक्षम करें; मैन्युअल बैकअप अभी भी काम करते हैं | -| `ENABLE_REQUEST_LOGS` | 'झूठा' | अनुरोध/प्रतिक्रिया लॉग सक्षम करता है | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | 'झूठा' | `सिक्योर` ऑथ कुकी को बाध्य करें (एचटीटीपीएस रिवर्स प्रॉक्सी के पीछे) | | `CLOUDFLARED_BIN` | परेशान | प्रबंधित डाउनलोड के बजाय मौजूदा `क्लाउडफ्लेयर्ड` बाइनरी का उपयोग करें | `क्लाउडफ्लेयर्ड_प्रोटोकॉल` | `http2` | प्रबंधित त्वरित सुरंगों के लिए परिवहन ('http2', 'त्वरित', या 'ऑटो') | @@ -693,15 +693,15 @@ Chain: production-fallback - दर सीमा का पता लगाने की संवेदनशीलता - घातीय बैकऑफ़ पैरामीटर -2.**संपादन योग्य दर सीमाएँ**— डैशबोर्ड में कॉन्फ़िगर करने योग्य सिस्टम-स्तरीय डिफ़ॉल्ट: -**प्रति मिनट अनुरोध (आरपीएम)**- प्रति खाता प्रति मिनट अधिकतम अनुरोध -**अनुरोधों के बीच न्यूनतम समय**- अनुरोधों के बीच मिलीसेकंड में न्यूनतम अंतर -**अधिकतम समवर्ती अनुरोध**— प्रति खाता अधिकतम एक साथ अनुरोध + 2.**संपादन योग्य दर सीमाएँ**— डैशबोर्ड में कॉन्फ़िगर करने योग्य सिस्टम-स्तरीय डिफ़ॉल्ट: -**प्रति मिनट अनुरोध (आरपीएम)**- प्रति खाता प्रति मिनट अधिकतम अनुरोध -**अनुरोधों के बीच न्यूनतम समय**- अनुरोधों के बीच मिलीसेकंड में न्यूनतम अंतर -**अधिकतम समवर्ती अनुरोध**— प्रति खाता अधिकतम एक साथ अनुरोध - संशोधित करने के लिए**संपादित करें**पर क्लिक करें, फिर**सहेजें**या**रद्द करें**पर क्लिक करें। मान लचीलापन एपीआई के माध्यम से बने रहते हैं। -3.**सर्किट ब्रेकर**- प्रति प्रदाता विफलताओं को ट्रैक करता है और सीमा तक पहुंचने पर स्वचालित रूप से सर्किट खोलता है: -**बंद**(स्वस्थ) - अनुरोध सामान्य रूप से प्रवाहित होते हैं -**खुला**- बार-बार विफलताओं के बाद प्रदाता अस्थायी रूप से अवरुद्ध हो जाता है -**आधा_खुला**— परीक्षण किया जा रहा है कि प्रदाता ठीक हो गया है या नहीं + 3.**सर्किट ब्रेकर**- प्रति प्रदाता विफलताओं को ट्रैक करता है और सीमा तक पहुंचने पर स्वचालित रूप से सर्किट खोलता है: -**बंद**(स्वस्थ) - अनुरोध सामान्य रूप से प्रवाहित होते हैं -**खुला**- बार-बार विफलताओं के बाद प्रदाता अस्थायी रूप से अवरुद्ध हो जाता है -**आधा_खुला**— परीक्षण किया जा रहा है कि प्रदाता ठीक हो गया है या नहीं -4.**नीतियाँ और लॉक किए गए पहचानकर्ता**- बल-अनलॉक क्षमता के साथ सर्किट ब्रेकर की स्थिति और लॉक किए गए पहचानकर्ताओं को दिखाता है। + 4.**नीतियाँ और लॉक किए गए पहचानकर्ता**- बल-अनलॉक क्षमता के साथ सर्किट ब्रेकर की स्थिति और लॉक किए गए पहचानकर्ताओं को दिखाता है। -5.**दर सीमा ऑटो-डिटेक्शन**- प्रदाता दर सीमा से बचने के लिए सक्रिय रूप से `429` और `पुनः प्रयास करें` हेडर पर नज़र रखता है। + 5.**दर सीमा ऑटो-डिटेक्शन**- प्रदाता दर सीमा से बचने के लिए सक्रिय रूप से `429` और `पुनः प्रयास करें` हेडर पर नज़र रखता है। **प्रो टिप:**जब कोई प्रदाता आउटेज से उबरता है तो सभी सर्किट ब्रेकर और कूलडाउन को साफ़ करने के लिए**रीसेट ऑल**बटन का उपयोग करें।--- diff --git a/docs/i18n/in/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/in/docs/VM_DEPLOYMENT_GUIDE.md index 5fdaaf8fe0..023fe14589 100644 --- a/docs/i18n/in/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/in/docs/VM_DEPLOYMENT_GUIDE.md @@ -99,7 +99,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/it/README.md b/docs/i18n/it/README.md index 6580fe5de9..89255c560b 100644 --- a/docs/i18n/it/README.md +++ b/docs/i18n/it/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Documentazione -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/it/docs/ARCHITECTURE.md b/docs/i18n/it/docs/ARCHITECTURE.md index 53cfb21642..13a22f202b 100644 --- a/docs/i18n/it/docs/ARCHITECTURE.md +++ b/docs/i18n/it/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/it/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/it/docs/CODEBASE_DOCUMENTATION.md index c15cef43b0..c15604ff61 100644 --- a/docs/i18n/it/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/it/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**: la pipeline di streaming principale. Due modalità: "TRANSLATE" (traduzione in formato completo) e "PASSTHROUGH" (normalizza + estrai l'utilizzo). Gestisce il buffering dei blocchi, la stima dell'utilizzo, il monitoraggio della lunghezza del contenuto. Le istanze del codificatore/decodificatore per flusso evitano lo stato condiviso. | | `streamHelpers.ts` | Utilità SSE di basso livello: `parseSSELine` (tollerante agli spazi bianchi), `hasValuableContent` (filtra blocchi vuoti per OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (serializzazione SSE sensibile al formato con pulizia `perf_metrics`). | | `usageTracking.ts` | Estrazione dell'utilizzo dei token da qualsiasi formato (Claude/OpenAI/Gemini/Responses), stima con rapporti separati strumento/messaggio caratteri per token, aggiunta buffer (margine di sicurezza di 2000 token), filtraggio dei campi specifici del formato, registrazione della console con colori ANSI. | -| `requestLogger.ts` | Registrazione delle richieste basata su file (attivazione tramite `ENABLE_REQUEST_LOGS=true`). Crea cartelle di sessione con file numerati: `1_req_client.json` → `7_res_client.txt`. Tutto l'I/O è asincrono (fire-and-forget). Maschera le intestazioni riservate. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Intercetta modelli specifici dalla CLI di Claude (estrazione del titolo, riscaldamento, conteggio) e restituisce risposte false senza chiamare alcun fornitore. Supporta sia lo streaming che il non streaming. Intenzionalmente limitato all'ambito CLI di Claude. | | `networkProxy.ts` | Risolve l'URL proxy in uscita per un determinato provider con precedenza: configurazione specifica del provider → configurazione globale → variabili di ambiente (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supporta le esclusioni "NO_PROXY". Configurazione della cache per 30 secondi. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/it/docs/TROUBLESHOOTING.md b/docs/i18n/it/docs/TROUBLESHOOTING.md index 9bef2b8c33..c3fff72693 100644 --- a/docs/i18n/it/docs/TROUBLESHOOTING.md +++ b/docs/i18n/it/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/it/docs/USER_GUIDE.md b/docs/i18n/it/docs/USER_GUIDE.md index 2f43e01f82..aeeb6131f1 100644 --- a/docs/i18n/it/docs/USER_GUIDE.md +++ b/docs/i18n/it/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `falso` | Consenti al gestore API di copiare le chiavi API complete su richiesta | | "PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES" | `70` | Cadenza di aggiornamento lato server per i dati sui limiti del provider memorizzati nella cache; I pulsanti di aggiornamento dell'interfaccia utente attivano ancora la sincronizzazione manuale | | `DISABLE_SQLITE_AUTO_BACKUP` | `falso` | Disabilitare gli snapshot SQLite automatici prima delle operazioni di scrittura/importazione/ripristino; i backup manuali funzionano ancora | -| `ENABLE_REQUEST_LOGS` | `falso` | Abilita i log di richiesta/risposta | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `falso` | Forza il cookie di autenticazione `Secure` (dietro il proxy inverso HTTPS) | | `CLOUDFLARED_BIN` | non impostato | Utilizza un file binario `cloudflared` esistente invece del download gestito | | `CLOUDFLARED_PROTOCOL` | "http2" | Trasporto per tunnel rapidi gestiti (`http2`, `quic` o `auto`) | @@ -692,15 +692,15 @@ OmniRoute implementa la resilienza a livello di fornitore con quattro componenti - Sensibilità di rilevamento del limite di velocità - Parametri di backoff esponenziale -2.**Limiti di velocità modificabili**: impostazioni predefinite a livello di sistema configurabili nel dashboard: -**Richieste al minuto (RPM)**: numero massimo di richieste al minuto per account -**Tempo minimo tra le richieste**: intervallo minimo in millisecondi tra le richieste -**Numero massimo di richieste simultanee**: numero massimo di richieste simultanee per account + 2.**Limiti di velocità modificabili**: impostazioni predefinite a livello di sistema configurabili nel dashboard: -**Richieste al minuto (RPM)**: numero massimo di richieste al minuto per account -**Tempo minimo tra le richieste**: intervallo minimo in millisecondi tra le richieste -**Numero massimo di richieste simultanee**: numero massimo di richieste simultanee per account - Fai clic su**Modifica**per modificare, quindi su**Salva**o**Annulla**. I valori persistono tramite l'API di resilienza. -3.**Interruttore di circuito**: tiene traccia dei guasti per fornitore e apre automaticamente il circuito quando viene raggiunta una soglia: -**CHIUSO**(integro): le richieste fluiscono normalmente -**APERTO**: il provider è temporaneamente bloccato dopo ripetuti errori -**HALF_OPEN**: verifica se il provider è stato ripristinato + 3.**Interruttore di circuito**: tiene traccia dei guasti per fornitore e apre automaticamente il circuito quando viene raggiunta una soglia: -**CHIUSO**(integro): le richieste fluiscono normalmente -**APERTO**: il provider è temporaneamente bloccato dopo ripetuti errori -**HALF_OPEN**: verifica se il provider è stato ripristinato -4.**Criteri e identificatori bloccati**: mostra lo stato dell'interruttore automatico e gli identificatori bloccati con funzionalità di sblocco forzato. + 4.**Criteri e identificatori bloccati**: mostra lo stato dell'interruttore automatico e gli identificatori bloccati con funzionalità di sblocco forzato. -5.**Rilevamento automatico del limite di velocità**: monitora le intestazioni "429" e "Retry-After" per evitare in modo proattivo di raggiungere i limiti di velocità del provider. + 5.**Rilevamento automatico del limite di velocità**: monitora le intestazioni "429" e "Retry-After" per evitare in modo proattivo di raggiungere i limiti di velocità del provider. **Pro Tip:**Use**Reset All**button to clear all circuit breakers and cooldowns when a provider recovers from an outage.--- diff --git a/docs/i18n/it/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/it/docs/VM_DEPLOYMENT_GUIDE.md index 8518293cf7..dd71aaca18 100644 --- a/docs/i18n/it/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/it/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/ja/README.md b/docs/i18n/ja/README.md index 0aeda24593..e314c6cf0e 100644 --- a/docs/i18n/ja/README.md +++ b/docs/i18n/ja/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## ドキュメント -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/ja/docs/ARCHITECTURE.md b/docs/i18n/ja/docs/ARCHITECTURE.md index 5a17df039a..dbbd7f50b0 100644 --- a/docs/i18n/ja/docs/ARCHITECTURE.md +++ b/docs/i18n/ja/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/ja/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/ja/docs/CODEBASE_DOCUMENTATION.md index 514eb3bdf5..2fc2c14c22 100644 --- a/docs/i18n/ja/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ja/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `ストリーム.ts` | **SSE Transform Stream**— コア ストリーミング パイプライン。 2 つのモード: `TRANSLATE` (完全な形式の変換) と `PASSTHROUGH` (正規化 + 使用法を抽出)。チャンクのバッファリング、使用量の推定、コンテンツの長さの追跡を処理します。ストリームごとのエンコーダ/デコーダ インスタンスは共有状態を回避します。 | | `streamHelpers.ts` | 低レベル SSE ユーティリティ: `parseSSELine` (ホワイトスペース耐性)、`hasValuableContent` (OpenAI/Claude/Gemini の空のチャンクをフィルタリング)、`fixInvalidId`、`formatSSE` (`perf_metrics` クリーンアップを使用したフォーマット認識 SSE シリアル化)。 | | `usageTracking.ts` | 任意の形式 (Claude/OpenAI/Gemini/Responses) からのトークン使用量の抽出、別個のツール/メッセージの文字数とトークンの比率による推定、バッファーの追加 (2000 トークンの安全マージン)、形式固有のフィールド フィルタリング、ANSI カラーでのコンソール ロギング。 | -| `requestLogger.ts` | ファイルベースのリクエストログ (「ENABLE_REQUEST_LOGS=true」によるオプトイン)。番号付きファイルを含むセッション フォルダーを作成します: `1_req_client.json` → `7_res_client.txt`。すべての I/O は非同期 (ファイア アンド フォーゲット) です。機密ヘッダーをマスクします。 | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Claude CLI からの特定のパターン (タイトル抽出、ウォームアップ、カウント) を傍受し、プロバイダーを呼び出さずに偽の応答を返します。ストリーミングと非ストリーミングの両方をサポートします。意図的に Claude CLI スコープに限定されています。 | | `ネットワークプロキシ.ts` | 指定されたプロバイダーの送信プロキシ URL を、プロバイダー固有の設定 → グローバル設定 → 環境変数 (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`) の優先順位で解決します。 「NO_PROXY」除外をサポートします。設定を 30 秒間キャッシュします。 | #### SSE Streaming Pipeline | diff --git a/docs/i18n/ja/docs/TROUBLESHOOTING.md b/docs/i18n/ja/docs/TROUBLESHOOTING.md index 54160df848..aa76ac8e50 100644 --- a/docs/i18n/ja/docs/TROUBLESHOOTING.md +++ b/docs/i18n/ja/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/ja/docs/USER_GUIDE.md b/docs/i18n/ja/docs/USER_GUIDE.md index a744bab252..437da7cff9 100644 --- a/docs/i18n/ja/docs/USER_GUIDE.md +++ b/docs/i18n/ja/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `偽` | API Manager が完全な API キーをオンデマンドでコピーできるようにする | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` |キャッシュされたプロバイダー制限データのサーバー側の更新頻度。 UI 更新ボタンは引き続き手動同期をトリガーします。 | `DISABLE_SQLITE_AUTO_BACKUP` | `偽` |書き込み/インポート/復元の前に自動 SQLite スナップショットを無効にします。手動バックアップは引き続き機能します。 -| `ENABLE_REQUEST_LOGS` | `偽` |リクエスト/レスポンスログを有効にする | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `偽` | 「セキュア」認証 Cookie を強制する (HTTPS リバース プロキシの背後で) | | `CLOUDFLARED_BIN` |設定を解除する |管理されたダウンロードの代わりに既存の「cloudflared」バイナリを使用します。 | `CLOUDFLARED_PROTOCOL` | `http2` |管理されたクイック トンネルのトランスポート (`http2`、`quic`、または `auto`) | @@ -691,15 +691,15 @@ OmniRoute は、次の 4 つのコンポーネントでプロバイダー レベ - レート制限検出感度 - 指数バックオフパラメータ -2.**編集可能なレート制限**— ダッシュボードで構成可能なシステムレベルのデフォルト: -**1 分あたりのリクエスト数 (RPM)**— アカウントごとの 1 分あたりの最大リクエスト数 -**リクエスト間の最小時間**— リクエスト間の最小ギャップ (ミリ秒単位) -**最大同時リクエスト**— アカウントあたりの最大同時リクエスト + 2.**編集可能なレート制限**— ダッシュボードで構成可能なシステムレベルのデフォルト: -**1 分あたりのリクエスト数 (RPM)**— アカウントごとの 1 分あたりの最大リクエスト数 -**リクエスト間の最小時間**— リクエスト間の最小ギャップ (ミリ秒単位) -**最大同時リクエスト**— アカウントあたりの最大同時リクエスト - [**編集**] をクリックして変更し、**保存**または**キャンセル**をクリックします。値は復元 API を介して保持されます。 -3.**サーキット ブレーカー**— プロバイダーごとに障害を追跡し、しきい値に達すると自動的に回線を開きます。-**クローズ**(正常) — リクエストは正常に流れます -**OPEN**— プロバイダーは失敗が繰り返された後、一時的にブロックされています -**HALF_OPEN**— プロバイダーが回復したかどうかをテストします + 3.**サーキット ブレーカー**— プロバイダーごとに障害を追跡し、しきい値に達すると自動的に回線を開きます。-**クローズ**(正常) — リクエストは正常に流れます -**OPEN**— プロバイダーは失敗が繰り返された後、一時的にブロックされています -**HALF_OPEN**— プロバイダーが回復したかどうかをテストします -4.**ポリシーとロックされた識別子**— 強制ロック解除機能を備えたサーキット ブレーカーのステータスとロックされた識別子を表示します。 + 4.**ポリシーとロックされた識別子**— 強制ロック解除機能を備えたサーキット ブレーカーのステータスとロックされた識別子を表示します。 -5.**レート制限の自動検出**- 「429」ヘッダーと「Retry-After」ヘッダーを監視して、プロバイダーのレート制限に達することを事前に回避します。 + 5.**レート制限の自動検出**- 「429」ヘッダーと「Retry-After」ヘッダーを監視して、プロバイダーのレート制限に達することを事前に回避します。 **プロのヒント:**プロバイダーが停止から回復したときに、**すべてリセット**ボタンを使用して、すべてのサーキット ブレーカーとクールダウンをクリアします。--- diff --git a/docs/i18n/ja/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ja/docs/VM_DEPLOYMENT_GUIDE.md index d88309e647..04a6830a1c 100644 --- a/docs/i18n/ja/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/ja/docs/VM_DEPLOYMENT_GUIDE.md @@ -99,7 +99,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/ko/README.md b/docs/i18n/ko/README.md index 2475f9cf55..8d2206e2f4 100644 --- a/docs/i18n/ko/README.md +++ b/docs/i18n/ko/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## 문서 -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/ko/docs/ARCHITECTURE.md b/docs/i18n/ko/docs/ARCHITECTURE.md index df58c9e9e4..d601a1d0b6 100644 --- a/docs/i18n/ko/docs/ARCHITECTURE.md +++ b/docs/i18n/ko/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/ko/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/ko/docs/CODEBASE_DOCUMENTATION.md index 88c1177f4a..0c22393683 100644 --- a/docs/i18n/ko/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ko/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE 변환 스트림**— 핵심 스트리밍 파이프라인입니다. 두 가지 모드: `TRANSLATE`(전체 형식 번역) 및 `PASSTHROUGH`(정규화 + 사용법 추출). 청크 버퍼링, 사용량 추정, 콘텐츠 길이 추적을 처리합니다. 스트림별 인코더/디코더 인스턴스는 공유 상태를 방지합니다. | | `streamHelpers.ts` | 하위 수준 SSE 유틸리티: `parseSSELine`(공백 허용), `hasValuableContent`(OpenAI/Claude/Gemini의 빈 청크 필터링), `fixInvalidId`, `formatSSE`(`perf_metrics` 정리를 통한 형식 인식 SSE 직렬화). | | `usageTracking.ts` | 모든 형식(Claude/OpenAI/Gemini/Responses)에서 토큰 사용량 추출, 별도 도구/토큰당 메시지 문자 비율을 사용한 추정, 버퍼 추가(2000 토큰 안전 마진), 형식별 필드 필터링, ANSI 색상을 사용한 콘솔 로깅. | -| `requestLogger.ts` | 파일 기반 요청 로깅(`ENABLE_REQUEST_LOGS=true`를 통해 선택). 번호가 매겨진 파일(`1_req_client.json` → `7_res_client.txt`)로 세션 폴더를 생성합니다. 모든 I/O는 비동기식입니다(fire-and-forget). 민감한 헤더를 마스킹합니다. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Claude CLI(제목 추출, 워밍업, 카운트)의 특정 패턴을 가로채고 공급자를 호출하지 않고 가짜 응답을 반환합니다. 스트리밍과 비스트리밍을 모두 지원합니다. 의도적으로 Claude CLI 범위로 제한되었습니다. | | `networkProxy.ts` | 공급자별 구성 → 전역 구성 → 환경 변수(`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`) 우선 순위에 따라 특정 공급자에 대한 아웃바운드 프록시 URL을 확인합니다. 'NO_PROXY' 제외를 지원합니다. 30초 동안 캐시 구성. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/ko/docs/TROUBLESHOOTING.md b/docs/i18n/ko/docs/TROUBLESHOOTING.md index 513a56549e..25cd67b3a9 100644 --- a/docs/i18n/ko/docs/TROUBLESHOOTING.md +++ b/docs/i18n/ko/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/ko/docs/USER_GUIDE.md b/docs/i18n/ko/docs/USER_GUIDE.md index 5f1c6f2cbf..84d2fa7b59 100644 --- a/docs/i18n/ko/docs/USER_GUIDE.md +++ b/docs/i18n/ko/docs/USER_GUIDE.md @@ -468,7 +468,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -500,7 +500,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | '거짓' | Api Manager가 요청 시 전체 API 키를 복사하도록 허용 | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | 캐시된 공급자 제한 데이터에 대한 서버측 새로 고침 주기. UI 새로 고침 버튼이 여전히 수동 동기화를 트리거합니다 | | DISABLE_SQLITE_AUTO_BACKUP` | '거짓' | 쓰기/가져오기/복원 전에 자동 SQLite 스냅샷을 비활성화합니다. 수동 백업은 여전히 ​​작동합니다 | -| `ENABLE_REQUEST_LOGS` | '거짓' | 요청/응답 로그 활성화 | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | '거짓' | '보안' 인증 쿠키 강제 적용(HTTPS 역방향 프록시 뒤) | | `CLOUDFLARED_BIN` | 설정되지 않음 | 관리형 다운로드 대신 기존 `cloudflared` 바이너리 사용 | | `CLOUDFLARED_PROTOCOL` | `http2` | 관리형 빠른 터널을 위한 전송(`http2`, `quic` 또는 `auto`) | @@ -692,15 +692,15 @@ OmniRoute는 다음 네 가지 구성 요소를 사용하여 공급자 수준 - 비율 제한 감지 감도 - 지수 백오프 매개변수 -2.**편집 가능한 속도 제한**— 대시보드에서 구성 가능한 시스템 수준 기본값: -**분당 요청(RPM)**— 계정당 분당 최대 요청 수 -**요청 간 최소 시간**— 요청 간 최소 간격(밀리초) -**최대 동시 요청**— 계정당 최대 동시 요청 + 2.**편집 가능한 속도 제한**— 대시보드에서 구성 가능한 시스템 수준 기본값: -**분당 요청(RPM)**— 계정당 분당 최대 요청 수 -**요청 간 최소 시간**— 요청 간 최소 간격(밀리초) -**최대 동시 요청**— 계정당 최대 동시 요청 - 수정하려면**수정**을 클릭한 다음**저장**또는**취소**를 클릭하세요. 값은 복원력 API를 통해 유지됩니다. -3.**회로 차단기**— 공급자별 오류를 추적하고 임계값에 도달하면 자동으로 회로를 엽니다. -**CLOSED**(정상) — 요청 흐름이 정상적으로 진행됩니다. -**OPEN**— 반복적인 실패 후 공급자가 일시적으로 차단됩니다. -**HALF_OPEN**— 공급자가 복구되었는지 테스트 + 3.**회로 차단기**— 공급자별 오류를 추적하고 임계값에 도달하면 자동으로 회로를 엽니다. -**CLOSED**(정상) — 요청 흐름이 정상적으로 진행됩니다. -**OPEN**— 반복적인 실패 후 공급자가 일시적으로 차단됩니다. -**HALF_OPEN**— 공급자가 복구되었는지 테스트 -4.**정책 및 잠긴 식별자**- 회로 차단기 상태와 강제 잠금 해제 기능이 있는 잠긴 식별자를 표시합니다. + 4.**정책 및 잠긴 식별자**- 회로 차단기 상태와 강제 잠금 해제 기능이 있는 잠긴 식별자를 표시합니다. -5.**비율 제한 자동 감지**— '429' 및 'Retry-After' 헤더를 모니터링하여 공급자 비율 제한에 도달하는 것을 사전에 방지합니다. + 5.**비율 제한 자동 감지**— '429' 및 'Retry-After' 헤더를 모니터링하여 공급자 비율 제한에 도달하는 것을 사전에 방지합니다. **프로 팁:**공급자가 중단에서 복구될 때**모두 재설정**버튼을 사용하여 모든 회로 차단기와 쿨다운을 해제합니다.--- diff --git a/docs/i18n/ko/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ko/docs/VM_DEPLOYMENT_GUIDE.md index d2f69129c7..855c336e40 100644 --- a/docs/i18n/ko/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/ko/docs/VM_DEPLOYMENT_GUIDE.md @@ -99,7 +99,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/ms/README.md b/docs/i18n/ms/README.md index 7e60a1580e..02a1921aa6 100644 --- a/docs/i18n/ms/README.md +++ b/docs/i18n/ms/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentasi -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/ms/docs/ARCHITECTURE.md b/docs/i18n/ms/docs/ARCHITECTURE.md index 53d2247396..a02e9741a1 100644 --- a/docs/i18n/ms/docs/ARCHITECTURE.md +++ b/docs/i18n/ms/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/ms/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/ms/docs/CODEBASE_DOCUMENTATION.md index 72dc81eb4c..4556b91197 100644 --- a/docs/i18n/ms/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ms/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— saluran paip penstriman teras. Dua mod: `TRANSLATE` (terjemahan format penuh) dan `PASTHROUGH` (normalkan + penggunaan ekstrak). Mengendalikan penimbalan bongkah, anggaran penggunaan, penjejakan panjang kandungan. Kejadian pengekod/penyahkod per strim mengelakkan keadaan dikongsi. | | `streamHelpers.ts` | Utiliti SSE peringkat rendah: `parseSSELine` (bertoleransi ruang putih), `hasValuableContent` (menapis bahagian kosong untuk OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (penyirian SSE sedar format dengan pembersihan `perf_metrics`). | | `usageTracking.ts` | Pengekstrakan penggunaan token daripada sebarang format (Claude/OpenAI/Gemini/Responses), anggaran dengan nisbah char-per-token alat/mesej yang berasingan, penambahan penimbal (margin keselamatan 2000 token), penapisan medan khusus format, pengelogan konsol dengan warna ANSI. | -| `requestLogger.ts` | Pengelogan permintaan berasaskan fail (ikut serta melalui `ENABLE_REQUEST_LOGS=true`). Mencipta folder sesi dengan fail bernombor: `1_req_client.json` → `7_res_client.txt`. Semua I/O tidak segerak (api-dan-lupa). Topeng tajuk sensitif. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Memintas corak tertentu daripada Claude CLI (pengeluaran tajuk, pemanasan, kiraan) dan mengembalikan respons palsu tanpa menghubungi mana-mana pembekal. Menyokong kedua-dua penstriman dan bukan penstriman. Sengaja dihadkan kepada skop Claude CLI. | | `networkProxy.ts` | Menyelesaikan URL proksi keluar untuk pembekal tertentu dengan keutamaan: konfigurasi khusus pembekal → konfigurasi global → pembolehubah persekitaran (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Menyokong pengecualian `NO_PROXY`. Konfigurasi cache untuk 30s. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/ms/docs/TROUBLESHOOTING.md b/docs/i18n/ms/docs/TROUBLESHOOTING.md index d7e1f9ac41..d323e46dfc 100644 --- a/docs/i18n/ms/docs/TROUBLESHOOTING.md +++ b/docs/i18n/ms/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/ms/docs/USER_GUIDE.md b/docs/i18n/ms/docs/USER_GUIDE.md index ec7cd66fc9..47f3894949 100644 --- a/docs/i18n/ms/docs/USER_GUIDE.md +++ b/docs/i18n/ms/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `BENARKAN_KUNCI_API_DEDAH` | `palsu` | Benarkan Pengurus Api menyalin kunci API penuh atas permintaan | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Irama penyegaran sisi pelayan untuk data Had Penyedia yang dicache; Butang muat semula UI masih mencetuskan penyegerakan manual | | `DISABLE_SQLITE_AUTO_BACKUP` | `palsu` | Lumpuhkan syot kilat SQLite automatik sebelum menulis/import/pulihkan; sandaran manual masih berfungsi | -| `ENABLE_REQUEST_LOGS` | `palsu` | Mendayakan log permintaan/tindak balas | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `palsu` | Paksa kuki pengesahan `Secure` (di belakang proksi terbalik HTTPS) | | `CLOUDFLARED_BIN` | tidak ditetapkan | Gunakan binari `cloudflared` sedia ada dan bukannya muat turun terurus | | `CLOUDFLARED_PROTOCOL` | `http2` | Pengangkutan untuk Terowong Pantas terurus (`http2`, `quic` atau `auto`) | @@ -692,15 +692,15 @@ OmniRoute melaksanakan daya tahan peringkat penyedia dengan empat komponen: - Sensitiviti pengesanan had kadar - Parameter mundur eksponen -2.**Had Kadar Boleh Diedit**— Lalai peringkat sistem boleh dikonfigurasikan dalam papan pemuka: -**Permintaan Per Minit (RPM)**— Permintaan maksimum seminit setiap akaun -**Masa Min Antara Permintaan**— Jurang minimum dalam milisaat antara permintaan -**Permintaan Serentak Maks**— Permintaan serentak maksimum bagi setiap akaun + 2.**Had Kadar Boleh Diedit**— Lalai peringkat sistem boleh dikonfigurasikan dalam papan pemuka: -**Permintaan Per Minit (RPM)**— Permintaan maksimum seminit setiap akaun -**Masa Min Antara Permintaan**— Jurang minimum dalam milisaat antara permintaan -**Permintaan Serentak Maks**— Permintaan serentak maksimum bagi setiap akaun - Klik**Edit**untuk mengubah suai, kemudian**Simpan**atau**Batal**. Nilai kekal melalui API ketahanan. -3.**Pemutus Litar**— Menjejaki kegagalan setiap pembekal dan membuka litar secara automatik apabila ambang dicapai: -**TUTUP**(Sihat) — Permintaan mengalir seperti biasa -**BUKA**— Pembekal disekat buat sementara waktu selepas kegagalan berulang -**HALF_OPEN**— Menguji jika pembekal telah pulih + 3.**Pemutus Litar**— Menjejaki kegagalan setiap pembekal dan membuka litar secara automatik apabila ambang dicapai: -**TUTUP**(Sihat) — Permintaan mengalir seperti biasa -**BUKA**— Pembekal disekat buat sementara waktu selepas kegagalan berulang -**HALF_OPEN**— Menguji jika pembekal telah pulih -4.**Dasar & Pengecam Terkunci**— Menunjukkan status pemutus litar dan pengecam terkunci dengan keupayaan buka kunci paksa. + 4.**Dasar & Pengecam Terkunci**— Menunjukkan status pemutus litar dan pengecam terkunci dengan keupayaan buka kunci paksa. -5.**Pengesanan Auto Had Kadar**— Memantau pengepala `429` dan `Retry-After` untuk mengelak daripada mencapai had kadar penyedia secara proaktif. + 5.**Pengesanan Auto Had Kadar**— Memantau pengepala `429` dan `Retry-After` untuk mengelak daripada mencapai had kadar penyedia secara proaktif. **Petua Pro:**Gunakan butang**Reset Semua**untuk mengosongkan semua pemutus litar dan cooldown apabila pembekal pulih daripada gangguan.--- diff --git a/docs/i18n/ms/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ms/docs/VM_DEPLOYMENT_GUIDE.md index d6f9a65602..3ddffe12fe 100644 --- a/docs/i18n/ms/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/ms/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/nl/README.md b/docs/i18n/nl/README.md index 0bf7fbda5a..4cd21ad60c 100644 --- a/docs/i18n/nl/README.md +++ b/docs/i18n/nl/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Documentatie -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/nl/docs/ARCHITECTURE.md b/docs/i18n/nl/docs/ARCHITECTURE.md index 14058f9e46..9aa7f8cd17 100644 --- a/docs/i18n/nl/docs/ARCHITECTURE.md +++ b/docs/i18n/nl/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/nl/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/nl/docs/CODEBASE_DOCUMENTATION.md index 0332e0da3e..a8a567a369 100644 --- a/docs/i18n/nl/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/nl/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— de belangrijkste streamingpijplijn. Twee modi: `TRANSLATE` (vertaling in volledig formaat) en `PASSTHROUGH` (normaliseren + extraheren van gebruik). Verwerkt chunkbuffering, gebruiksschatting en het bijhouden van de inhoudslengte. Encoder/decoder-instanties per stream vermijden een gedeelde status. | | `streamHelpers.ts` | SSE-hulpprogramma's op laag niveau: `parseSSELine` (witruimtetolerant), `hasValuableContent` (filtert lege chunks voor OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (formaatbewuste SSE-serialisatie met opschoning van `perf_metrics`). | | `usageTracking.ts` | Extractie van tokengebruik uit elk formaat (Claude/OpenAI/Gemini/Responses), schatting met afzonderlijke tool/bericht-char-per-token-verhoudingen, buffertoevoeging (veiligheidsmarge van 2000 tokens), formaatspecifieke veldfiltering, consolelogboekregistratie met ANSI-kleuren. | -| `requestLogger.ts` | Op bestanden gebaseerde registratie van verzoeken (opt-in via `ENABLE_REQUEST_LOGS=true`). Creëert sessiemappen met genummerde bestanden: `1_req_client.json` → `7_res_client.txt`. Alle I/O is async (fire-and-forget). Maskert gevoelige headers. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Onderschept specifieke patronen van Claude CLI (titelextractie, opwarming, telling) en retourneert valse antwoorden zonder een provider te bellen. Ondersteunt zowel streaming als niet-streaming. Opzettelijk beperkt tot het Claude CLI-bereik. | | `netwerkProxy.ts` | Bepaalt de uitgaande proxy-URL voor een bepaalde provider met voorrang: providerspecifieke configuratie → globale configuratie → omgevingsvariabelen (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Ondersteunt 'NO_PROXY'-uitsluitingen. Cachesconfiguratie voor 30s. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/nl/docs/TROUBLESHOOTING.md b/docs/i18n/nl/docs/TROUBLESHOOTING.md index 15dc7ab895..73318dcf0b 100644 --- a/docs/i18n/nl/docs/TROUBLESHOOTING.md +++ b/docs/i18n/nl/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/nl/docs/USER_GUIDE.md b/docs/i18n/nl/docs/USER_GUIDE.md index 4270518aab..19f8d118b9 100644 --- a/docs/i18n/nl/docs/USER_GUIDE.md +++ b/docs/i18n/nl/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `vals` | Sta Api Manager toe om op aanvraag volledige API-sleutels te kopiëren | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Verversingsfrequentie aan de serverzijde voor in de cache opgeslagen Provider Limits-gegevens; Knoppen voor het vernieuwen van de gebruikersinterface activeren nog steeds handmatige synchronisatie | | `DISABLE_SQLITE_AUTO_BACKUP` | `vals` | Schakel automatische SQLite-snapshots uit vóór schrijven/importeren/herstellen; handmatige back-ups werken nog steeds | -| `ENABLE_REQUEST_LOGS` | `vals` | Schakelt verzoek-/antwoordlogboeken in | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `vals` | Forceer `Secure` auth-cookie (achter HTTPS reverse proxy) | | `CLOUDFLARED_BIN` | uitgeschakeld | Gebruik een bestaand `cloudflared` binair bestand in plaats van een beheerde download | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport voor beheerde Quick Tunnels (`http2`, `quic` of `auto`) | @@ -692,15 +692,15 @@ OmniRoute implementeert veerkracht op providerniveau met vier componenten: - Snelheidslimietdetectiegevoeligheid - Exponentiële uitstelparameters -2.**Bewerkbare tarieflimieten**— Standaardinstellingen op systeemniveau configureerbaar in het dashboard: -**Verzoeken per minuut (RPM)**— Maximaal aantal verzoeken per minuut per account -**Min. tijd tussen verzoeken**— Minimale pauze in milliseconden tussen verzoeken -**Max. gelijktijdige verzoeken**— Maximaal gelijktijdige verzoeken per account + 2.**Bewerkbare tarieflimieten**— Standaardinstellingen op systeemniveau configureerbaar in het dashboard: -**Verzoeken per minuut (RPM)**— Maximaal aantal verzoeken per minuut per account -**Min. tijd tussen verzoeken**— Minimale pauze in milliseconden tussen verzoeken -**Max. gelijktijdige verzoeken**— Maximaal gelijktijdige verzoeken per account - Klik op**Bewerken**om te wijzigen en vervolgens op**Opslaan**of**Annuleren**. Waarden blijven behouden via de veerkracht-API. -3.**Circuit Breaker**— Volgt storingen per provider en opent automatisch het circuit wanneer een drempel wordt bereikt: -**GESLOTEN**(Gezond) — Verzoeken stromen normaal door -**OPEN**— Provider is tijdelijk geblokkeerd na herhaalde fouten -**HALF_OPEN**— Testen of de provider is hersteld + 3.**Circuit Breaker**— Volgt storingen per provider en opent automatisch het circuit wanneer een drempel wordt bereikt: -**GESLOTEN**(Gezond) — Verzoeken stromen normaal door -**OPEN**— Provider is tijdelijk geblokkeerd na herhaalde fouten -**HALF_OPEN**— Testen of de provider is hersteld -4.**Beleid en vergrendelde identificatiegegevens**— Toont de status van de stroomonderbreker en vergrendelde identificatiegegevens met de mogelijkheid tot geforceerd ontgrendelen. + 4.**Beleid en vergrendelde identificatiegegevens**— Toont de status van de stroomonderbreker en vergrendelde identificatiegegevens met de mogelijkheid tot geforceerd ontgrendelen. -5.**Automatische detectie van snelheidslimiet**— Controleert de headers '429' en 'Retry-After' om proactief te voorkomen dat de tarieflimieten van de provider worden overschreden. + 5.**Automatische detectie van snelheidslimiet**— Controleert de headers '429' en 'Retry-After' om proactief te voorkomen dat de tarieflimieten van de provider worden overschreden. **Pro-tip:**Gebruik de knop**Alles resetten**om alle stroomonderbrekers en cooldowns te wissen wanneer een provider herstelt van een storing.--- diff --git a/docs/i18n/nl/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/nl/docs/VM_DEPLOYMENT_GUIDE.md index 0345bef74e..f66e758c73 100644 --- a/docs/i18n/nl/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/nl/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/no/README.md b/docs/i18n/no/README.md index b61342156b..ba60001100 100644 --- a/docs/i18n/no/README.md +++ b/docs/i18n/no/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentasjon -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/no/docs/ARCHITECTURE.md b/docs/i18n/no/docs/ARCHITECTURE.md index 187931d9fd..db5cef383a 100644 --- a/docs/i18n/no/docs/ARCHITECTURE.md +++ b/docs/i18n/no/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/no/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/no/docs/CODEBASE_DOCUMENTATION.md index f46ef253a4..cda39a316e 100644 --- a/docs/i18n/no/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/no/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— kjernestrømmingsrørledningen. To moduser: 'OVERSET' (oversettelse i fullformat) og 'PASSTHROUGH' (normaliser + ekstrak bruk). Håndterer chunk-buffring, bruksestimat, sporing av innholdslengde. Per-stream koder/dekoderforekomster unngår delt tilstand. | | `streamHelpers.ts` | SSE-verktøy på lavt nivå: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filtrerer tomme biter for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (formatbevisst SSE-serialisering med `perf_metrics`-opprydding). | | `usageTracking.ts` | Uttrekk av tokenbruk fra ethvert format (Claude/OpenAI/Gemini/Responses), estimering med separate verktøy/melding-char-per-token-forhold, buffertillegg (sikkerhetsmargin for 2000 tokens), formatspesifikk feltfiltrering, konsolllogging med ANSI-farger. | -| `requestLogger.ts` | Filbasert forespørselslogging (velg på via `ENABLE_REQUEST_LOGS=true`). Oppretter øktmapper med nummererte filer: `1_req_client.json` → `7_res_client.txt`. All I/O er asynkron (fire-and-forget). Maskerer sensitive overskrifter. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Avskjærer spesifikke mønstre fra Claude CLI (tittelutvinning, oppvarming, telling) og returnerer falske svar uten å ringe noen leverandør. Støtter både streaming og ikke-streaming. Med vilje begrenset til Claude CLI-omfang. | | `networkProxy.ts` | Løser utgående proxy-URL for en gitt leverandør med prioritet: leverandørspesifikk konfig → global konfig → miljøvariabler (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Støtter "NO_PROXY"-ekskluderinger. Cacher konfigurasjon for 30s. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/no/docs/TROUBLESHOOTING.md b/docs/i18n/no/docs/TROUBLESHOOTING.md index d2adcbf47f..2224f4e674 100644 --- a/docs/i18n/no/docs/TROUBLESHOOTING.md +++ b/docs/i18n/no/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/no/docs/USER_GUIDE.md b/docs/i18n/no/docs/USER_GUIDE.md index 4bb52e00a7..2ed7cc8b14 100644 --- a/docs/i18n/no/docs/USER_GUIDE.md +++ b/docs/i18n/no/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `false` | Tillat at Api Manager kopierer fullstendige API-nøkler på forespørsel | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Oppdateringskadens på tjenersiden for bufrede Provider Limits-data; UI-oppdateringsknapper utløser fortsatt manuell synkronisering | | `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Deaktiver automatiske SQLite-øyeblikksbilder før skriving/importering/gjenoppretting; manuelle sikkerhetskopier fungerer fortsatt | -| `ENABLE_REQUEST_LOGS` | `false` | Aktiverer forespørsels-/svarlogger | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `false` | Tving `Sikker` auth-informasjonskapsel (bak HTTPS omvendt proxy) | | `CLOUDFLARED_BIN` | deaktivert | Bruk en eksisterende `cloudflared`-binær i stedet for administrert nedlasting | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport for administrerte hurtigtunneler (`http2`, `quic` eller `auto`) | @@ -692,15 +692,15 @@ OmniRoute implementerer motstandskraft på leverandørnivå med fire komponenter - Følsomhet for deteksjon av hastighetsgrense - Eksponentielle backoff-parametere -2.**Redigerbare rategrenser**— Standardinnstillinger på systemnivå som kan konfigureres i dashbordet: -**Forespørsler per minutt (RPM)**— Maksimalt antall forespørsler per minutt per konto -**Min time Between Requests**— Minimumsavstand i millisekunder mellom forespørsler -**Maks samtidige forespørsler**— Maksimalt antall samtidige forespørsler per konto + 2.**Redigerbare rategrenser**— Standardinnstillinger på systemnivå som kan konfigureres i dashbordet: -**Forespørsler per minutt (RPM)**— Maksimalt antall forespørsler per minutt per konto -**Min time Between Requests**— Minimumsavstand i millisekunder mellom forespørsler -**Maks samtidige forespørsler**— Maksimalt antall samtidige forespørsler per konto - Klikk på**Rediger**for å endre, deretter**Lagre**eller**Avbryt**. Verdiene vedvarer via resilience API. -3.**Circuit Breaker**— Sporer feil per leverandør og åpner automatisk kretsen når en terskel er nådd: -**STENGT**(Sunn) — Forespørslene flyter normalt -**ÅPEN**— Leverandøren er midlertidig blokkert etter gjentatte feil -**HALF_OPEN**— Tester om leverandøren har kommet seg + 3.**Circuit Breaker**— Sporer feil per leverandør og åpner automatisk kretsen når en terskel er nådd: -**STENGT**(Sunn) — Forespørslene flyter normalt -**ÅPEN**— Leverandøren er midlertidig blokkert etter gjentatte feil -**HALF_OPEN**— Tester om leverandøren har kommet seg -4.**Retningslinjer og låste identifikatorer**— Viser strømbryterstatus og låste identifikatorer med tvangsopplåsingsfunksjon. + 4.**Retningslinjer og låste identifikatorer**— Viser strømbryterstatus og låste identifikatorer med tvangsopplåsingsfunksjon. -5.**Rate Limit Auto-Detection**— Overvåker «429» og «Retry-After»-overskrifter for å proaktivt unngå å treffe leverandørens takstgrenser. + 5.**Rate Limit Auto-Detection**— Overvåker «429» og «Retry-After»-overskrifter for å proaktivt unngå å treffe leverandørens takstgrenser. **Profftips:**Bruk**Tilbakestill alle**-knappen for å fjerne alle strømbrytere og nedkjøling når en leverandør kommer seg etter et strømbrudd.--- diff --git a/docs/i18n/no/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/no/docs/VM_DEPLOYMENT_GUIDE.md index ae550a3219..1de5a1d62a 100644 --- a/docs/i18n/no/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/no/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/phi/README.md b/docs/i18n/phi/README.md index 5754f04f93..46aee141f1 100644 --- a/docs/i18n/phi/README.md +++ b/docs/i18n/phi/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentasyon -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/phi/docs/ARCHITECTURE.md b/docs/i18n/phi/docs/ARCHITECTURE.md index e38832b682..71d6270208 100644 --- a/docs/i18n/phi/docs/ARCHITECTURE.md +++ b/docs/i18n/phi/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/phi/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/phi/docs/CODEBASE_DOCUMENTATION.md index a569b94329..e8ae1b1eec 100644 --- a/docs/i18n/phi/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/phi/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— ang pangunahing streaming pipeline. Dalawang mode: `TRANSLATE` (full format translation) at `PASSTHROUGH` (normalize + ang paggamit ng extract). Pinangangasiwaan ang chunk buffering, pagtatantya ng paggamit, pagsubaybay sa haba ng nilalaman. Ang mga instance ng per-stream encoder/decoder ay umiiwas sa nakabahaging estado. | | `streamHelpers.ts` | Mga utility na mababa ang antas ng SSE: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filter ang mga walang laman na chunks para sa OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization na may `perf_metrics` cleanup). | | `usageTracking.ts` | Pagkuha ng paggamit ng token mula sa anumang format (Claude/OpenAI/Gemini/Responses), pagtatantya na may hiwalay na tool/message char-per-token ratios, pagdaragdag ng buffer (2000 token safety margin), pag-filter ng field na partikular sa format, console logging na may mga kulay ng ANSI. | -| `requestLogger.ts` | Nakabatay sa file ang pag-log ng kahilingan (opt-in sa pamamagitan ng `ENABLE_REQUEST_LOGS=true`). Gumagawa ng mga folder ng session na may mga file na may numero: `1_req_client.json` → `7_res_client.txt`. Ang lahat ng I/O ay async (fire-and-forget). Maskara ang mga sensitibong header. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Hinaharang ang mga partikular na pattern mula kay Claude CLI (pagkuha ng pamagat, warmup, count) at ibinabalik ang mga pekeng tugon nang hindi tumatawag sa anumang provider. Sinusuportahan ang parehong streaming at hindi streaming. Sinasadyang limitado sa saklaw ng Claude CLI. | | `networkProxy.ts` | Nire-resolve ang outbound proxy URL para sa isang ibinigay na provider nang nangunguna: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Sinusuportahan ang mga pagbubukod ng `NO_PROXY`. Caches config para sa 30s. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/phi/docs/TROUBLESHOOTING.md b/docs/i18n/phi/docs/TROUBLESHOOTING.md index d61631edc5..31d9e0f17a 100644 --- a/docs/i18n/phi/docs/TROUBLESHOOTING.md +++ b/docs/i18n/phi/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/phi/docs/USER_GUIDE.md b/docs/i18n/phi/docs/USER_GUIDE.md index 42a2fbbe7b..30a0f5ae11 100644 --- a/docs/i18n/phi/docs/USER_GUIDE.md +++ b/docs/i18n/phi/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `false` | Payagan ang Api Manager na kopyahin ang buong API keys on demand | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Server-side refresh cadence para sa naka-cache na data ng Mga Limitasyon ng Provider; Ang mga button ng pag-refresh ng UI ay nagti-trigger pa rin ng manu-manong pag-sync | | `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Huwag paganahin ang mga awtomatikong snapshot ng SQLite bago magsulat/mag-import/mag-restore; gumagana pa rin ang mga manu-manong backup | -| `ENABLE_REQUEST_LOGS` | `false` | Pinapagana ang mga log ng kahilingan/tugon | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `false` | Pilitin ang `Secure` auth cookie (sa likod ng HTTPS reverse proxy) | | `CLOUDFLARED_BIN` | hindi nakatakda | Gumamit ng kasalukuyang binary na `cloudflared` sa halip na pinamamahalaang pag-download | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport para sa pinamamahalaang Quick Tunnels (`http2`, `quic`, o `auto`) | @@ -692,15 +692,15 @@ Ang OmniRoute ay nagpapatupad ng pagiging matatag sa antas ng provider na may ap - Rate limit detection sensitivity - Exponential backoff na mga parameter -2.**Editable Rate Limits**— System-level defaults configurable sa dashboard: -**Requests Per Minute (RPM)**— Mga maximum na kahilingan kada minuto bawat account -**Min Time Between Requests**— Minimum na agwat sa millisecond sa pagitan ng mga kahilingan -**Max Kasabay na Kahilingan**— Pinakamataas na sabay-sabay na kahilingan sa bawat account + 2.**Editable Rate Limits**— System-level defaults configurable sa dashboard: -**Requests Per Minute (RPM)**— Mga maximum na kahilingan kada minuto bawat account -**Min Time Between Requests**— Minimum na agwat sa millisecond sa pagitan ng mga kahilingan -**Max Kasabay na Kahilingan**— Pinakamataas na sabay-sabay na kahilingan sa bawat account - I-click ang**I-edit**upang baguhin, pagkatapos ay**I-save**o**Kanselahin**. Nananatili ang mga halaga sa pamamagitan ng resilience API. -3.**Circuit Breaker**— Sinusubaybayan ang mga pagkabigo sa bawat provider at awtomatikong bubuksan ang circuit kapag naabot ang isang threshold: -**SARADO**(Healthy) — Normal na dumadaloy ang mga kahilingan -**OPEN**— Pansamantalang naka-block ang provider pagkatapos ng paulit-ulit na pagkabigo -**HALF_OPEN**— Pagsubok kung nakabawi na ang provider + 3.**Circuit Breaker**— Sinusubaybayan ang mga pagkabigo sa bawat provider at awtomatikong bubuksan ang circuit kapag naabot ang isang threshold: -**SARADO**(Healthy) — Normal na dumadaloy ang mga kahilingan -**OPEN**— Pansamantalang naka-block ang provider pagkatapos ng paulit-ulit na pagkabigo -**HALF_OPEN**— Pagsubok kung nakabawi na ang provider -4.**Mga Patakaran at Mga Naka-lock na Identifier**— Nagpapakita ng status ng circuit breaker at mga naka-lock na identifier na may kakayahan sa force-unlock. + 4.**Mga Patakaran at Mga Naka-lock na Identifier**— Nagpapakita ng status ng circuit breaker at mga naka-lock na identifier na may kakayahan sa force-unlock. -5.**Awtomatikong Pagtukoy sa Limitasyon ng Rate**— Sinusubaybayan ang mga header ng `429` at `Retry-After` upang aktibong maiwasang maabot ang mga limitasyon sa rate ng provider. + 5.**Awtomatikong Pagtukoy sa Limitasyon ng Rate**— Sinusubaybayan ang mga header ng `429` at `Retry-After` upang aktibong maiwasang maabot ang mga limitasyon sa rate ng provider. **Pro Tip:**Gamitin ang**I-reset Lahat**na button para i-clear ang lahat ng mga circuit breaker at cooldown kapag gumaling ang isang provider mula sa isang outage.--- diff --git a/docs/i18n/phi/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/phi/docs/VM_DEPLOYMENT_GUIDE.md index 72ec656aab..bdc7a7df56 100644 --- a/docs/i18n/phi/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/phi/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/pl/README.md b/docs/i18n/pl/README.md index c86e155267..240a0d14ae 100644 --- a/docs/i18n/pl/README.md +++ b/docs/i18n/pl/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentacja -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/pl/docs/ARCHITECTURE.md b/docs/i18n/pl/docs/ARCHITECTURE.md index 42c05dae89..f0a274bfbe 100644 --- a/docs/i18n/pl/docs/ARCHITECTURE.md +++ b/docs/i18n/pl/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/pl/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/pl/docs/CODEBASE_DOCUMENTATION.md index 470f4ff901..b5303003ef 100644 --- a/docs/i18n/pl/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/pl/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `strumień.ts` | **SSE Transform Stream**— główny potok przesyłania strumieniowego. Dwa tryby: `TRANSLATE` (tłumaczenie w pełnym formacie) i `PASSTHROUGH` (normalizacja + wyodrębnienie użycia). Obsługuje buforowanie fragmentów, szacowanie użycia, śledzenie długości treści. Instancje kodera/dekodera na strumień unikają stanu współdzielonego. | | `streamHelpers.ts` | Narzędzia SSE niskiego poziomu: `parseSSELine` (tolerujący białe znaki), `hasValuableContent` (filtruje puste fragmenty dla OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (serializacja SSE uwzględniająca format z czyszczeniem `perf_metrics`). | | `usageTracking.ts` | Ekstrakcja użycia tokena z dowolnego formatu (Claude/OpenAI/Gemini/Responses), szacowanie za pomocą oddzielnych współczynników znaków na token narzędzia/wiadomości, dodanie bufora (margines bezpieczeństwa 2000 tokenów), filtrowanie pól specyficzne dla formatu, rejestrowanie konsoli za pomocą kolorów ANSI. | -| `requestLogger.ts` | Rejestrowanie żądań w oparciu o pliki (opcja poprzez `ENABLE_REQUEST_LOGS=true`). Tworzy foldery sesji z ponumerowanymi plikami: `1_req_client.json` → `7_res_client.txt`. Wszystkie wejścia/wyjścia są asynchroniczne (odpal i zapomnij). Maskuje wrażliwe nagłówki. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Przechwytuje określone wzorce z Claude CLI (wyodrębnianie tytułu, rozgrzewka, liczenie) i zwraca fałszywe odpowiedzi bez wywoływania żadnego dostawcy. Obsługuje zarówno przesyłanie strumieniowe, jak i inne. Celowo ograniczone do zakresu Claude CLI. | | `networkProxy.ts` | Rozwiązuje wychodzący adres URL proxy dla danego dostawcy z pierwszeństwem: konfiguracja specyficzna dla dostawcy → konfiguracja globalna → zmienne środowiskowe (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`. Obsługuje wykluczenia `NO_PROXY`. Buforuje konfigurację przez 30 sekund. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/pl/docs/TROUBLESHOOTING.md b/docs/i18n/pl/docs/TROUBLESHOOTING.md index c75630df0e..43f38df521 100644 --- a/docs/i18n/pl/docs/TROUBLESHOOTING.md +++ b/docs/i18n/pl/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/pl/docs/USER_GUIDE.md b/docs/i18n/pl/docs/USER_GUIDE.md index c6d3c25a22..2fe855c387 100644 --- a/docs/i18n/pl/docs/USER_GUIDE.md +++ b/docs/i18n/pl/docs/USER_GUIDE.md @@ -468,7 +468,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -500,7 +500,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `fałszywy` | Zezwalaj Api Managerowi na kopiowanie pełnych kluczy API na żądanie | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Częstotliwość odświeżania po stronie serwera buforowanych danych dotyczących limitów dostawcy; Przyciski odświeżania interfejsu użytkownika nadal uruchamiają ręczną synchronizację | | `WYŁĄCZ_SQLITE_AUTO_BACKUP` | `fałszywy` | Wyłącz automatyczne migawki SQLite przed zapisem/importem/przywróceniem; ręczne kopie zapasowe nadal działają | -| `ENABLE_REQUEST_LOGS` | `fałszywy` | Włącza dzienniki żądań/odpowiedzi | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `fałszywy` | Wymuś „bezpieczny” plik cookie uwierzytelniający (za odwrotnym proxy HTTPS) | | `CLOUDFLARED_BIN` | rozbrojony | Użyj istniejącego pliku binarnego `cloudflared` zamiast zarządzanego pobierania | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport dla zarządzanych szybkich tuneli (`http2`, `quic` lub `auto`) | @@ -693,15 +693,15 @@ OmniRoute wdraża odporność na poziomie dostawcy za pomocą czterech komponent - Czułość wykrywania limitu szybkości - Wykładnicze parametry wycofywania -2.**Edytowalne limity prędkości**— Domyślne ustawienia na poziomie systemu można skonfigurować w panelu kontrolnym: -**Żądania na minutę (RPM)**— Maksymalna liczba żądań na minutę na konto -**Min. czas między żądaniami**— Minimalna przerwa w milisekundach między żądaniami -**Maksymalna liczba jednoczesnych żądań**— Maksymalna liczba jednoczesnych żądań na konto + 2.**Edytowalne limity prędkości**— Domyślne ustawienia na poziomie systemu można skonfigurować w panelu kontrolnym: -**Żądania na minutę (RPM)**— Maksymalna liczba żądań na minutę na konto -**Min. czas między żądaniami**— Minimalna przerwa w milisekundach między żądaniami -**Maksymalna liczba jednoczesnych żądań**— Maksymalna liczba jednoczesnych żądań na konto - Kliknij**Edytuj**, aby zmodyfikować, a następnie**Zapisz**lub**Anuluj**. Wartości są zachowywane za pośrednictwem interfejsu API odporności. -3.**Wyłącznik**— śledzi awarie według dostawcy i automatycznie otwiera obwód po osiągnięciu progu: -**ZAMKNIĘTE**(zdrowe) — Żądania przebiegają normalnie -**OTWARTE**— Dostawca jest tymczasowo blokowany po powtarzających się awariach -**HALF_OPEN**— Sprawdzanie, czy dostawca powrócił do zdrowia + 3.**Wyłącznik**— śledzi awarie według dostawcy i automatycznie otwiera obwód po osiągnięciu progu: -**ZAMKNIĘTE**(zdrowe) — Żądania przebiegają normalnie -**OTWARTE**— Dostawca jest tymczasowo blokowany po powtarzających się awariach -**HALF_OPEN**— Sprawdzanie, czy dostawca powrócił do zdrowia -4.**Zasady i zablokowane identyfikatory**— Pokazuje stan wyłącznika automatycznego i zablokowane identyfikatory z możliwością wymuszonego odblokowania. + 4.**Zasady i zablokowane identyfikatory**— Pokazuje stan wyłącznika automatycznego i zablokowane identyfikatory z możliwością wymuszonego odblokowania. -5.**Automatyczne wykrywanie limitu szybkości**— Monitoruje nagłówki „429” i „Retry-After”, aby aktywnie zapobiegać przekroczeniu limitów szybkości dostawcy. + 5.**Automatyczne wykrywanie limitu szybkości**— Monitoruje nagłówki „429” i „Retry-After”, aby aktywnie zapobiegać przekroczeniu limitów szybkości dostawcy. **Wskazówka dla profesjonalistów:**Użyj przycisku**Resetuj wszystko**, aby wyczyścić wszystkie wyłączniki automatyczne i czasy odnowienia, gdy dostawca wznowi działanie po awarii.--- diff --git a/docs/i18n/pl/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/pl/docs/VM_DEPLOYMENT_GUIDE.md index ed3b074cb9..2545839361 100644 --- a/docs/i18n/pl/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/pl/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/pt-BR/README.md b/docs/i18n/pt-BR/README.md index b3ee1b033f..8fa83980c1 100644 --- a/docs/i18n/pt-BR/README.md +++ b/docs/i18n/pt-BR/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Documentação -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/pt-BR/docs/ARCHITECTURE.md b/docs/i18n/pt-BR/docs/ARCHITECTURE.md index d8e29eb828..2d7bcb7da8 100644 --- a/docs/i18n/pt-BR/docs/ARCHITECTURE.md +++ b/docs/i18n/pt-BR/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/pt-BR/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/pt-BR/docs/CODEBASE_DOCUMENTATION.md index 9b9497d46b..a856f9f79b 100644 --- a/docs/i18n/pt-BR/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/pt-BR/docs/CODEBASE_DOCUMENTATION.md @@ -405,7 +405,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. | | `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). | | `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. | -| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. | | `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. | diff --git a/docs/i18n/pt-BR/docs/TROUBLESHOOTING.md b/docs/i18n/pt-BR/docs/TROUBLESHOOTING.md index b627c270ef..e602c4cc4d 100644 --- a/docs/i18n/pt-BR/docs/TROUBLESHOOTING.md +++ b/docs/i18n/pt-BR/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/pt-BR/docs/USER_GUIDE.md b/docs/i18n/pt-BR/docs/USER_GUIDE.md index d40db81c18..8eac29d065 100644 --- a/docs/i18n/pt-BR/docs/USER_GUIDE.md +++ b/docs/i18n/pt-BR/docs/USER_GUIDE.md @@ -493,7 +493,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -524,7 +524,7 @@ post_install() { | `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Server-side refresh cadence for cached Provider Limits data; UI refresh buttons still trigger manual sync | | `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work | -| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) | | `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport for managed Quick Tunnels (`http2`, `quic`, or `auto`) | diff --git a/docs/i18n/pt-BR/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/pt-BR/docs/VM_DEPLOYMENT_GUIDE.md index 42e7d694b1..d26416e0f4 100644 --- a/docs/i18n/pt-BR/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/pt-BR/docs/VM_DEPLOYMENT_GUIDE.md @@ -108,7 +108,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/pt/README.md b/docs/i18n/pt/README.md index 11d72c1eb3..e8a1b441f6 100644 --- a/docs/i18n/pt/README.md +++ b/docs/i18n/pt/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Documentação -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/pt/docs/ARCHITECTURE.md b/docs/i18n/pt/docs/ARCHITECTURE.md index dac4ff9094..abed39145b 100644 --- a/docs/i18n/pt/docs/ARCHITECTURE.md +++ b/docs/i18n/pt/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/pt/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/pt/docs/CODEBASE_DOCUMENTATION.md index 973b6caf42..3ed41d3334 100644 --- a/docs/i18n/pt/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/pt/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— o principal pipeline de streaming. Dois modos: `TRANSLATE` (tradução de formato completo) e `PASSTHROUGH` (normalizar + extrair o uso). Lida com buffer de blocos, estimativa de uso e rastreamento de comprimento de conteúdo. As instâncias do codificador/decodificador por fluxo evitam o estado compartilhado. | | `streamHelpers.ts` | Utilitários SSE de baixo nível: `parseSSELine` (tolerante a espaços em branco), `hasValuableContent` (filtra pedaços vazios para OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (serialização SSE com reconhecimento de formato com limpeza `perf_metrics`). | | `usageTracking.ts` | Extração de uso de token de qualquer formato (Claude/OpenAI/Gemini/Responses), estimativa com proporções separadas de caracteres por ferramenta/mensagem por token, adição de buffer (margem de segurança de 2.000 tokens), filtragem de campo específica de formato, registro de console com cores ANSI. | -| `requestLogger.ts` | Registro de solicitação baseado em arquivo (opt-in via `ENABLE_REQUEST_LOGS=true`). Cria pastas de sessão com arquivos numerados: `1_req_client.json` → `7_res_client.txt`. Toda E/S é assíncrona (dispare e esqueça). Mascara cabeçalhos sensíveis. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Intercepta padrões específicos do Claude CLI (extração de título, aquecimento, contagem) e retorna respostas falsas sem ligar para nenhum provedor. Suporta streaming e não streaming. Intencionalmente limitado ao escopo Claude CLI. | | `networkProxy.ts` | Resolve URL de proxy de saída para um determinado provedor com precedência: configuração específica do provedor → configuração global → variáveis ​​de ambiente (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Suporta exclusões `NO_PROXY`. Configuração de caches por 30s. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/pt/docs/TROUBLESHOOTING.md b/docs/i18n/pt/docs/TROUBLESHOOTING.md index 382b3717f0..35debe53e8 100644 --- a/docs/i18n/pt/docs/TROUBLESHOOTING.md +++ b/docs/i18n/pt/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/pt/docs/USER_GUIDE.md b/docs/i18n/pt/docs/USER_GUIDE.md index d262ade2ee..a41d2f2a1c 100644 --- a/docs/i18n/pt/docs/USER_GUIDE.md +++ b/docs/i18n/pt/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `falso` | Permitir que o Api Manager copie chaves de API completas sob demanda | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Cadência de atualização do lado do servidor para dados armazenados em cache do Provider Limits; Os botões de atualização da IU ainda acionam a sincronização manual | | `DISABLE_SQLITE_AUTO_BACKUP` | `falso` | Desative os instantâneos automáticos do SQLite antes de gravar/importar/restaurar; backups manuais ainda funcionam | -| `ENABLE_REQUEST_LOGS` | `falso` | Habilita registros de solicitação/resposta | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `falso` | Forçar cookie de autenticação `Secure` (por trás do proxy reverso HTTPS) | | `CLOUDFLARED_BIN` | desarmar | Use um binário `cloudflared` existente em vez de download gerenciado | | `CLOUDFLARED_PROTOCOL` | `http2` | Transporte para Quick Tunnels gerenciados (`http2`, `quic` ou `auto`) | @@ -692,15 +692,15 @@ OmniRoute implementa resiliência em nível de provedor com quatro componentes: - Sensibilidade de detecção de limite de taxa - Parâmetros de espera exponencial -2.**Limites de taxa editáveis**— Padrões de nível de sistema configuráveis no painel: -**Solicitações por minuto (RPM)**— Máximo de solicitações por minuto por conta -**Tempo mínimo entre solicitações**— Intervalo mínimo em milissegundos entre solicitações -**Máximo de solicitações simultâneas**— Máximo de solicitações simultâneas por conta + 2.**Limites de taxa editáveis**— Padrões de nível de sistema configuráveis no painel: -**Solicitações por minuto (RPM)**— Máximo de solicitações por minuto por conta -**Tempo mínimo entre solicitações**— Intervalo mínimo em milissegundos entre solicitações -**Máximo de solicitações simultâneas**— Máximo de solicitações simultâneas por conta - Clique em**Editar**para modificar e depois em**Salvar**ou**Cancelar**. Os valores persistem por meio da API de resiliência. -3.**Disjuntor**— Rastreia falhas por provedor e abre automaticamente o circuito quando um limite é atingido: -**FECHADO**(Saudável) — As solicitações fluem normalmente -**OPEN**— O provedor é bloqueado temporariamente após falhas repetidas -**HALF_OPEN**— Testando se o provedor se recuperou + 3.**Disjuntor**— Rastreia falhas por provedor e abre automaticamente o circuito quando um limite é atingido: -**FECHADO**(Saudável) — As solicitações fluem normalmente -**OPEN**— O provedor é bloqueado temporariamente após falhas repetidas -**HALF_OPEN**— Testando se o provedor se recuperou -4.**Políticas e identificadores bloqueados**— Mostra o status do disjuntor e identificadores bloqueados com capacidade de desbloqueio forçado. + 4.**Políticas e identificadores bloqueados**— Mostra o status do disjuntor e identificadores bloqueados com capacidade de desbloqueio forçado. -5.**Detecção automática de limite de taxa**— Monitora os cabeçalhos `429` e `Retry-After` para evitar proativamente atingir os limites de taxa do provedor. + 5.**Detecção automática de limite de taxa**— Monitora os cabeçalhos `429` e `Retry-After` para evitar proativamente atingir os limites de taxa do provedor. **Dica profissional:**Use o botão**Redefinir tudo**para limpar todos os disjuntores e resfriamentos quando um provedor se recupera de uma interrupção.--- diff --git a/docs/i18n/pt/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/pt/docs/VM_DEPLOYMENT_GUIDE.md index 1552276fb5..b2fa91b7c3 100644 --- a/docs/i18n/pt/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/pt/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/ro/README.md b/docs/i18n/ro/README.md index fe29812f84..7945e09734 100644 --- a/docs/i18n/ro/README.md +++ b/docs/i18n/ro/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Documentație -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/ro/docs/ARCHITECTURE.md b/docs/i18n/ro/docs/ARCHITECTURE.md index 4ce36c0e3b..fc8cd7d87c 100644 --- a/docs/i18n/ro/docs/ARCHITECTURE.md +++ b/docs/i18n/ro/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/ro/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/ro/docs/CODEBASE_DOCUMENTATION.md index 69fb2fde64..694a37f1f5 100644 --- a/docs/i18n/ro/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ro/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— canalul de streaming de bază. Două moduri: `TRANSLATE` (traducere în format complet) și `PASSTHROUGH` (normalizare + extragere utilizare). Se ocupă de stocarea în tampon, estimarea utilizării, urmărirea duratei conținutului. Instanțele de codificator/decodor per-stream evită starea partajată. | | `streamHelpers.ts` | Utilitare SSE de nivel scăzut: `parseSSELine` (tolerant la spații albe), `hasValuableContent` (filtrează bucățile goale pentru OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (serializare SSE conștientă de format cu curățare `perf_metrics`). | | `usageTracking.ts` | Extragerea utilizării jetoanelor din orice format (Claude/OpenAI/Gemini/Responses), estimare cu rapoarte separate pentru instrumente/mesaj, adăugare de buffer (marja de siguranță de 2000 de jetoane), filtrare câmp specific formatului, înregistrare în consolă cu culori ANSI. | -| `requestLogger.ts` | Înregistrarea cererilor pe bază de fișier (înregistrare prin `ENABLE_REQUEST_LOGS=true`). Creează foldere de sesiune cu fișiere numerotate: `1_req_client.json` → `7_res_client.txt`. Toate I/O sunt asincrone (foc și uitare). Mască anteturile sensibile. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Interceptează modele specifice din Claude CLI (extragere titlu, încălzire, numărare) și returnează răspunsuri false fără a apela niciun furnizor. Suportă atât streaming, cât și non-streaming. Limitat intenționat la domeniul Claude CLI. | | `networkProxy.ts` | Rezolvă URL-ul proxy de ieșire pentru un anumit furnizor cu prioritate: configurație specifică furnizorului → configurație globală → variabile de mediu (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Acceptă excluderile „NO_PROXY”. Memorează în cache configurația pentru 30 de secunde. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/ro/docs/TROUBLESHOOTING.md b/docs/i18n/ro/docs/TROUBLESHOOTING.md index e603e9c1e6..6ecda9a66f 100644 --- a/docs/i18n/ro/docs/TROUBLESHOOTING.md +++ b/docs/i18n/ro/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/ro/docs/USER_GUIDE.md b/docs/i18n/ro/docs/USER_GUIDE.md index 7e6d3d4fa8..f494164822 100644 --- a/docs/i18n/ro/docs/USER_GUIDE.md +++ b/docs/i18n/ro/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `fals` | Permiteți Managerului Api să copieze chei API complete la cerere | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | cadență de reîmprospătare la nivelul serverului pentru datele din cache ale Limitelor furnizorului; Butoanele de reîmprospătare a interfeței de utilizator declanșează în continuare sincronizarea manuală | | `DISABLE_SQLITE_AUTO_BACKUP` | `fals` | Dezactivați instantaneele automate SQLite înainte de scriere/import/restaurare; backup-urile manuale încă funcționează | -| `ENABLE_REQUEST_LOGS` | `fals` | Activează jurnalele cereri/răspuns | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `fals` | Forțați cookie-ul de autentificare „Securizat” (în spatele proxy-ului invers HTTPS) | | `CLOUDFLARED_BIN` | dezactivat | Utilizați un binar `cloudflared` existent în loc de descărcare gestionată | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport pentru tuneluri rapide gestionate (`http2`, `quic` sau `auto`) | @@ -692,15 +692,15 @@ OmniRoute implementează rezistența la nivel de furnizor cu patru componente: - Sensibilitatea de detectare a limitei ratei - Parametrii de backoff exponenţial -2.**Limite de rată editabile**— Setări implicite la nivel de sistem configurabile în tabloul de bord: -**Solicitări pe minut (RPM)**— Numărul maxim de solicitări pe minut per cont -**Timp minim între solicitări**— Intervalul minim în milisecunde între solicitări -**Max. de solicitări simultane**— Maxim de solicitări simultane per cont + 2.**Limite de rată editabile**— Setări implicite la nivel de sistem configurabile în tabloul de bord: -**Solicitări pe minut (RPM)**— Numărul maxim de solicitări pe minut per cont -**Timp minim între solicitări**— Intervalul minim în milisecunde între solicitări -**Max. de solicitări simultane**— Maxim de solicitări simultane per cont - Faceți clic pe**Editați**pentru a modifica, apoi pe**Salvați**sau**Anulați**. Valorile persistă prin intermediul API-ului de rezistență. -3.**Circuit Breaker**— Urmărește defecțiunile pentru fiecare furnizor și deschide automat circuitul când este atins un prag: -**ÎNCHIS**(sănătos) — Solicitările curg normal -**DESCHIS**— Furnizorul este blocat temporar după eșecuri repetate -**HALF_OPEN**— Se testează dacă furnizorul și-a revenit + 3.**Circuit Breaker**— Urmărește defecțiunile pentru fiecare furnizor și deschide automat circuitul când este atins un prag: -**ÎNCHIS**(sănătos) — Solicitările curg normal -**DESCHIS**— Furnizorul este blocat temporar după eșecuri repetate -**HALF_OPEN**— Se testează dacă furnizorul și-a revenit -4.**Politici și identificatori blocați**— Afișează starea întrerupătorului și identificatorii blocați cu capacitatea de deblocare forțată. + 4.**Politici și identificatori blocați**— Afișează starea întrerupătorului și identificatorii blocați cu capacitatea de deblocare forțată. -5.**Rate Limit Auto-Detection**— Monitorizează anteturile `429` și `Retry-After` pentru a evita în mod proactiv atingerea limitelor de rate ale furnizorului. + 5.**Rate Limit Auto-Detection**— Monitorizează anteturile `429` și `Retry-After` pentru a evita în mod proactiv atingerea limitelor de rate ale furnizorului. **Sfat profesionist:**Folosiți butonul**Reset All**pentru a șterge toate întreruptoarele de circuit și perioadele de răcire atunci când un furnizor își revine după o întrerupere.--- diff --git a/docs/i18n/ro/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ro/docs/VM_DEPLOYMENT_GUIDE.md index 70ec1d897a..61fd23bfcb 100644 --- a/docs/i18n/ro/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/ro/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/ru/README.md b/docs/i18n/ru/README.md index 3fac1f2779..8c4239c0e1 100644 --- a/docs/i18n/ru/README.md +++ b/docs/i18n/ru/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Документация -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/ru/docs/ARCHITECTURE.md b/docs/i18n/ru/docs/ARCHITECTURE.md index bf593c582a..0efe2f926a 100644 --- a/docs/i18n/ru/docs/ARCHITECTURE.md +++ b/docs/i18n/ru/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/ru/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/ru/docs/CODEBASE_DOCUMENTATION.md index 33b4c2ec52..8c87f4234c 100644 --- a/docs/i18n/ru/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/ru/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— основной конвейер потоковой передачи. Два режима: `TRANSLATE` (полноформатный перевод) и `PASSTHROUGH` (нормализация + использование извлечения). Управляет буферизацией фрагментов, оценкой использования, отслеживанием длины контента. Экземпляры попоточного кодировщика/декодера избегают общего состояния. | | `streamHelpers.ts` | Утилиты SSE низкого уровня: parseSSELine (устойчив к пробелам), hasValuableContent (фильтрует пустые фрагменты для OpenAI/Claude/Gemini), fixInvalidId, formatSSE (сериализация SSE с учетом формата с очисткой perf_metrics). | | `usageTracking.ts` | Извлечение использования токенов из любого формата (Claude/OpenAI/Gemini/Responses), оценка с помощью отдельных соотношений инструмента/сообщения на токен, добавление буфера (запас безопасности 2000 токенов), фильтрация полей для конкретного формата, ведение журнала консоли с цветами ANSI. | -| `requestLogger.ts` | Ведение журнала запросов на основе файлов (включение через ENABLE_REQUEST_LOGS=true). Создает папки сеансов с пронумерованными файлами: `1_req_client.json` → `7_res_client.txt`. Весь ввод-вывод является асинхронным (выстрелил и забыл). Маскирует чувствительные заголовки. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Перехватывает определенные шаблоны из Claude CLI (извлечение заголовков, прогрев, подсчет) и возвращает поддельные ответы без вызова какого-либо провайдера. Поддерживает как потоковую, так и непотоковую передачу. Намеренно ограничено областью CLI Claude. | | `networkProxy.ts` | Разрешает URL-адрес исходящего прокси-сервера для данного провайдера с приоритетом: конфигурация конкретного провайдера → глобальная конфигурация → переменные среды (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Кэширует конфиг на 30 секунд. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/ru/docs/TROUBLESHOOTING.md b/docs/i18n/ru/docs/TROUBLESHOOTING.md index eeb4ac8263..fb708e353b 100644 --- a/docs/i18n/ru/docs/TROUBLESHOOTING.md +++ b/docs/i18n/ru/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/ru/docs/USER_GUIDE.md b/docs/i18n/ru/docs/USER_GUIDE.md index 7f097098db..34de24980d 100644 --- a/docs/i18n/ru/docs/USER_GUIDE.md +++ b/docs/i18n/ru/docs/USER_GUIDE.md @@ -468,7 +468,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -500,7 +500,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `ложь` | Разрешить Api Manager копировать полные ключи API по требованию | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Частота обновления на стороне сервера кэшированных данных о лимитах поставщика; Кнопки обновления пользовательского интерфейса по-прежнему запускают ручную синхронизацию | | `DISABLE_SQLITE_AUTO_BACKUP` | `ложь` | Отключить автоматическое создание снимков SQLite перед записью/импортом/восстановлением; резервное копирование вручную все еще работает | -| `ENABLE_REQUEST_LOGS` | `ложь` | Включает журналы запросов/ответов | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `ложь` | Принудительно использовать файл cookie аутентификации `Secure` (за обратным прокси-сервером HTTPS) | | `CLOUDFLARED_BIN` | не установлен | Использовать существующий двоичный файл «cloudflared» вместо управляемой загрузки | | `CLOUDFLARED_PROTOCOL` | `http2` | Транспорт для управляемых быстрых туннелей (http2, quic или auto) | @@ -693,14 +693,14 @@ OmniRoute реализует устойчивость на уровне пост - Чувствительность определения ограничения скорости - Параметры экспоненциальной отсрочки -2.**Редактируемые ограничения скорости**— настройки по умолчанию на уровне системы, которые можно настроить на панели управления: -**Запросов в минуту (RPM)**— максимальное количество запросов в минуту на аккаунт. -**Min Time Between Requests**— Минимальный промежуток в миллисекундах между запросами. -**Максимальное количество одновременных запросов**— максимальное количество одновременных запросов на одну учетную запись. -– Нажмите**Изменить**, чтобы изменить, затем**Сохранить**или**Отменить**. Значения сохраняются через API устойчивости. + 2.**Редактируемые ограничения скорости**— настройки по умолчанию на уровне системы, которые можно настроить на панели управления: -**Запросов в минуту (RPM)**— максимальное количество запросов в минуту на аккаунт. -**Min Time Between Requests**— Минимальный промежуток в миллисекундах между запросами. -**Максимальное количество одновременных запросов**— максимальное количество одновременных запросов на одну учетную запись. + – Нажмите**Изменить**, чтобы изменить, затем**Сохранить**или**Отменить**. Значения сохраняются через API устойчивости. -3.**Прерыватель цепи**— отслеживает сбои каждого провайдера и автоматически размыкает цепь при достижении порогового значения: -**ЗАКРЫТО**(Исправно) — запросы выполняются нормально. -**OPEN**— Провайдер временно заблокирован после повторных сбоев. -**HALF_OPEN**— Проверка восстановления провайдера + 3.**Прерыватель цепи**— отслеживает сбои каждого провайдера и автоматически размыкает цепь при достижении порогового значения: -**ЗАКРЫТО**(Исправно) — запросы выполняются нормально. -**OPEN**— Провайдер временно заблокирован после повторных сбоев. -**HALF_OPEN**— Проверка восстановления провайдера -4.**Политики и заблокированные идентификаторы**— отображает состояние автоматического выключателя и заблокированные идентификаторы с возможностью принудительной разблокировки. + 4.**Политики и заблокированные идентификаторы**— отображает состояние автоматического выключателя и заблокированные идентификаторы с возможностью принудительной разблокировки. -5.**Автоматическое определение ограничения скорости** — отслеживает заголовки `429` и `Retry-After`, чтобы заранее избежать превышения ограничений скорости провайдера. + 5.**Автоматическое определение ограничения скорости** — отслеживает заголовки `429` и `Retry-After`, чтобы заранее избежать превышения ограничений скорости провайдера. **Совет для профессионалов.**Используйте кнопку**Сбросить все**, чтобы сбросить все автоматические выключатели и время восстановления, когда поставщик услуг восстанавливается после сбоя.--- diff --git a/docs/i18n/ru/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ru/docs/VM_DEPLOYMENT_GUIDE.md index b90278ae12..449d5dfb87 100644 --- a/docs/i18n/ru/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/ru/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/sk/README.md b/docs/i18n/sk/README.md index 424aaecd52..ef733442cf 100644 --- a/docs/i18n/sk/README.md +++ b/docs/i18n/sk/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentácia -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/sk/docs/ARCHITECTURE.md b/docs/i18n/sk/docs/ARCHITECTURE.md index 0447587be4..c62231deea 100644 --- a/docs/i18n/sk/docs/ARCHITECTURE.md +++ b/docs/i18n/sk/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/sk/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/sk/docs/CODEBASE_DOCUMENTATION.md index 7bb99a0ca3..32dbaf6033 100644 --- a/docs/i18n/sk/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/sk/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**– hlavný streamingový kanál. Dva režimy: `TRANSLATE` (preklad plného formátu) a `PASSTHROUGH` (normalizovať + extrahovať použitie). Rieši ukladanie kúskov do vyrovnávacej pamäte, odhad využitia, sledovanie dĺžky obsahu. Inštancie kódovača/dekodéra podľa prúdu sa vyhýbajú zdieľanému stavu. | | `streamHelpers.ts` | Nízkoúrovňové nástroje SSE: `parseSSELine` (tolerujúce biele miesta), `hasValuableContent` (filtruje prázdne časti pre OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (sérializácia SSE s ohľadom na formát s vyčistením `perf_metrics`). | | `usageTracking.ts` | Extrakcia použitia tokenov z ľubovoľného formátu (Claude/OpenAI/Gemini/Responses), odhad so samostatnými pomermi znakov na token/nástroje/správy, pridanie do vyrovnávacej pamäte (bezpečnostná rezerva 2000 tokenov), filtrovanie polí podľa formátu, protokolovanie konzoly s farbami ANSI. | -| `requestLogger.ts` | Protokolovanie žiadostí založené na súboroch (prihlásenie cez `ENABLE_REQUEST_LOGS=true`). Vytvára priečinky relácie s očíslovanými súbormi: `1_req_client.json` → `7_res_client.txt`. Všetky I/O sú asynchrónne (fire-and-forget). Maskuje citlivé hlavičky. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Zachytáva špecifické vzory z Claude CLI (extrakcia titulov, zahrievanie, počet) a vracia falošné odpovede bez volania akéhokoľvek poskytovateľa. Podporuje streamovanie aj nestreamovanie. Zámerne obmedzené na rozsah Claude CLI. | | `networkProxy.ts` | Vyrieši adresu URL odchádzajúcej proxy pre daného poskytovateľa s prioritou: konfigurácia špecifická pre poskytovateľa → globálna konfigurácia → premenné prostredia (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Podporuje vylúčenia „NO_PROXY“. Konfiguráciu vyrovnávacej pamäte na 30 s. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/sk/docs/TROUBLESHOOTING.md b/docs/i18n/sk/docs/TROUBLESHOOTING.md index 308b8d379a..b44373f934 100644 --- a/docs/i18n/sk/docs/TROUBLESHOOTING.md +++ b/docs/i18n/sk/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/sk/docs/USER_GUIDE.md b/docs/i18n/sk/docs/USER_GUIDE.md index 7e66d3c63a..1b3c1a588f 100644 --- a/docs/i18n/sk/docs/USER_GUIDE.md +++ b/docs/i18n/sk/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | "nepravda" | Povoliť Správcovi API kopírovať úplné kľúče API na požiadanie | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | "70" | Kadencia obnovovania na strane servera pre údaje limitov poskytovateľa uložené vo vyrovnávacej pamäti; Tlačidlá obnovenia používateľského rozhrania stále spúšťajú manuálnu synchronizáciu | | `DISABLE_SQLITE_AUTO_BACKUP` | "nepravda" | Zakázať automatické snímky SQLite pred zápisom/importom/obnovením; manuálne zálohovanie stále funguje | -| `ENABLE_REQUEST_LOGS` | "nepravda" | Povolí protokoly požiadaviek/odpovedí | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | „AUTH_COOKIE_SECURE“ | "nepravda" | Vynútiť „Secure“ auth cookie (za HTTPS reverzným proxy serverom) | | `CLOUDFLARED_BIN` | deaktivovaný | Namiesto riadeného sťahovania použite existujúci binárny súbor „cloudflared“ | | `CLOUDFLARED_PROTOCOL` | "http2" | Transport pre spravované rýchle tunely (`http2`, `quic` alebo `auto`) | @@ -693,15 +693,15 @@ OmniRoute implementuje odolnosť na úrovni poskytovateľa so štyrmi komponentm - Citlivosť detekcie limitu rýchlosti - Exponenciálne parametre backoff -2.**Upraviteľné limity rýchlosti**— Predvolené nastavenia na úrovni systému konfigurovateľné na paneli: -**Požiadavky za minútu (RPM)**– Maximálny počet žiadostí za minútu na účet -**Min Time Between Requests**– Minimálna medzera v milisekundách medzi požiadavkami -**Max Concurrent Requests**– Maximálny počet simultánnych požiadaviek na účet + 2.**Upraviteľné limity rýchlosti**— Predvolené nastavenia na úrovni systému konfigurovateľné na paneli: -**Požiadavky za minútu (RPM)**– Maximálny počet žiadostí za minútu na účet -**Min Time Between Requests**– Minimálna medzera v milisekundách medzi požiadavkami -**Max Concurrent Requests**– Maximálny počet simultánnych požiadaviek na účet - Kliknite na**Upraviť**a upravte, potom na**Uložiť**alebo**Zrušiť**. Hodnoty pretrvávajú prostredníctvom rozhrania API odolnosti. -3.**Circuit Breaker**– Sleduje zlyhania podľa poskytovateľa a automaticky otvára okruh, keď sa dosiahne prah: -**ZATVORENÉ**(zdravé) – požiadavky prebiehajú normálne -**OPEN**— Poskytovateľ je po opakovaných zlyhaniach dočasne zablokovaný -**HALF_OPEN**– Testuje sa, či sa poskytovateľ zotavil + 3.**Circuit Breaker**– Sleduje zlyhania podľa poskytovateľa a automaticky otvára okruh, keď sa dosiahne prah: -**ZATVORENÉ**(zdravé) – požiadavky prebiehajú normálne -**OPEN**— Poskytovateľ je po opakovaných zlyhaniach dočasne zablokovaný -**HALF_OPEN**– Testuje sa, či sa poskytovateľ zotavil -4.**Policies & Locked Identifiers**– Zobrazuje stav ističa a uzamknuté identifikátory s možnosťou vynútenia odomknutia. + 4.**Policies & Locked Identifiers**– Zobrazuje stav ističa a uzamknuté identifikátory s možnosťou vynútenia odomknutia. -5.**Automatická detekcia limitu rýchlosti**— Monitoruje hlavičky `429` a `Retry-After`, aby sa proaktívne vyhlo prekročeniu limitov sadzby poskytovateľa. + 5.**Automatická detekcia limitu rýchlosti**— Monitoruje hlavičky `429` a `Retry-After`, aby sa proaktívne vyhlo prekročeniu limitov sadzby poskytovateľa. **Tip pre profesionálov:**Použite tlačidlo**Reset All**na vymazanie všetkých ističov a chladenia, keď sa poskytovateľ zotaví z výpadku.--- diff --git a/docs/i18n/sk/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/sk/docs/VM_DEPLOYMENT_GUIDE.md index 68bf4cbb15..f719181423 100644 --- a/docs/i18n/sk/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/sk/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/sv/README.md b/docs/i18n/sv/README.md index b41860c18d..629636f400 100644 --- a/docs/i18n/sv/README.md +++ b/docs/i18n/sv/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Dokumentation -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/sv/docs/ARCHITECTURE.md b/docs/i18n/sv/docs/ARCHITECTURE.md index 85240cadb1..34707da414 100644 --- a/docs/i18n/sv/docs/ARCHITECTURE.md +++ b/docs/i18n/sv/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/sv/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/sv/docs/CODEBASE_DOCUMENTATION.md index 3dba537378..32cb9e7126 100644 --- a/docs/i18n/sv/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/sv/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— kärnan för streaming. Två lägen: 'ÖVERSÄTT' (översättning i fullformat) och 'PASSTHROUGH' (normalisera + extrahera användning). Hanterar chunkbuffring, användningsuppskattning, spårning av innehållslängd. Encoder/decoder-instanser per ström undviker delat tillstånd. | | `streamHelpers.ts` | SSE-verktyg på låg nivå: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filtrerar tomma bitar för OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (formatmedveten SSE-serialisering med `perf_metrics`-rensning). | | `usageTracking.ts` | Extrahering av tokenanvändning från valfritt format (Claude/OpenAI/Gemini/Responses), uppskattning med separata verktyg/meddelande-char-per-token-förhållanden, bufferttillägg (säkerhetsmarginal för 2000 tokens), formatspecifik fältfiltrering, konsolloggning med ANSI-färger. | -| `requestLogger.ts` | Filbaserad förfrågningsloggning (opt-in via `ENABLE_REQUEST_LOGS=true`). Skapar sessionsmappar med numrerade filer: `1_req_client.json` → `7_res_client.txt`. All I/O är asynkron (eld-och-glöm). Maskerar känsliga rubriker. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Fångar upp specifika mönster från Claude CLI (titelextraktion, uppvärmning, räkning) och returnerar falska svar utan att ringa någon leverantör. Stöder både streaming och icke-streaming. Avsiktligt begränsad till Claude CLI omfattning. | | `networkProxy.ts` | Löser utgående proxy-URL för en given leverantör med prioritet: leverantörsspecifik konfiguration → global konfiguration → miljövariabler (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Stöder "NO_PROXY"-undantag. Caches konfiguration för 30s. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/sv/docs/TROUBLESHOOTING.md b/docs/i18n/sv/docs/TROUBLESHOOTING.md index 10a5c207b9..a64baf4b47 100644 --- a/docs/i18n/sv/docs/TROUBLESHOOTING.md +++ b/docs/i18n/sv/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/sv/docs/USER_GUIDE.md b/docs/i18n/sv/docs/USER_GUIDE.md index 2bedbc1667..5bd0881999 100644 --- a/docs/i18n/sv/docs/USER_GUIDE.md +++ b/docs/i18n/sv/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `falskt` | Tillåt Api Manager att kopiera fullständiga API-nycklar på begäran | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Uppdateringskadens på serversidan för cachelagrade Provider Limits-data; UI-uppdateringsknappar utlöser fortfarande manuell synkronisering | | `DISABLE_SQLITE_AUTO_BACKUP` | `falskt` | Inaktivera automatiska SQLite-ögonblicksbilder före skrivning/import/återställning; manuella säkerhetskopieringar fungerar fortfarande | -| `ENABLE_REQUEST_LOGS` | `falskt` | Aktiverar förfrågnings-/svarsloggar | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `falskt` | Tvinga "Säker" auth-cookie (bakom HTTPS omvänd proxy) | | `CLOUDFLARED_BIN` | avstängd | Använd en befintlig `cloudflared`-binär istället för hanterad nedladdning | | `CLOUDFLARED_PROTOCOL` | `http2` | Transport för hanterade snabba tunnlar (`http2`, `quic` eller `auto`) | @@ -692,15 +692,15 @@ OmniRoute implementerar motståndskraft på leverantörsnivå med fyra komponent - Känslighet för detektering av hastighetsgräns - Exponentiell backoff-parametrar -2.**Redigerbara hastighetsgränser**— Standardinställningar på systemnivå som kan konfigureras i instrumentpanelen: -**Requests Per Minute (RPM)**— Maximalt antal förfrågningar per minut och konto -**Minsta tid mellan förfrågningar**— Minsta mellanrum i millisekunder mellan förfrågningar -**Max samtidiga förfrågningar**— Maximalt antal samtidiga förfrågningar per konto + 2.**Redigerbara hastighetsgränser**— Standardinställningar på systemnivå som kan konfigureras i instrumentpanelen: -**Requests Per Minute (RPM)**— Maximalt antal förfrågningar per minut och konto -**Minsta tid mellan förfrågningar**— Minsta mellanrum i millisekunder mellan förfrågningar -**Max samtidiga förfrågningar**— Maximalt antal samtidiga förfrågningar per konto - Klicka på**Redigera**för att ändra och sedan på**Spara**eller**Avbryt**. Värden kvarstår via resilience API. -3.**Circuit Breaker**— Spårar fel per leverantör och öppnar automatiskt kretsen när ett tröskelvärde nås: -**STÄNGD**(frisk) — Begäran flyter normalt -**ÖPPEN**— Leverantören är tillfälligt blockerad efter upprepade fel -**HALF_OPEN**— Testar om leverantören har återhämtat sig + 3.**Circuit Breaker**— Spårar fel per leverantör och öppnar automatiskt kretsen när ett tröskelvärde nås: -**STÄNGD**(frisk) — Begäran flyter normalt -**ÖPPEN**— Leverantören är tillfälligt blockerad efter upprepade fel -**HALF_OPEN**— Testar om leverantören har återhämtat sig -4.**Policy & Locked Identifiers**— Visar strömbrytarens status och låsta identifierare med tvångsupplåsning. + 4.**Policy & Locked Identifiers**— Visar strömbrytarens status och låsta identifierare med tvångsupplåsning. -5.**Rate Limit Auto-Detection**— Övervakar rubrikerna "429" och "Retry-After" för att proaktivt undvika att nå leverantörshastighetsgränser. + 5.**Rate Limit Auto-Detection**— Övervakar rubrikerna "429" och "Retry-After" för att proaktivt undvika att nå leverantörshastighetsgränser. **Proffstips:**Använd knappen**Återställ alla**för att rensa alla strömbrytare och nedkylningar när en leverantör återhämtar sig efter ett avbrott.--- diff --git a/docs/i18n/sv/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/sv/docs/VM_DEPLOYMENT_GUIDE.md index f6235830c8..f9db0e95d1 100644 --- a/docs/i18n/sv/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/sv/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/th/README.md b/docs/i18n/th/README.md index 0561d2d441..be6f502550 100644 --- a/docs/i18n/th/README.md +++ b/docs/i18n/th/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## เอกสาร -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/th/docs/ARCHITECTURE.md b/docs/i18n/th/docs/ARCHITECTURE.md index fba6b1b965..3e528297aa 100644 --- a/docs/i18n/th/docs/ARCHITECTURE.md +++ b/docs/i18n/th/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/th/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/th/docs/CODEBASE_DOCUMENTATION.md index eff197f140..9f8a0cb441 100644 --- a/docs/i18n/th/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/th/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— ไปป์ไลน์การสตรีมหลัก สองโหมด: `TRANSLATE` (การแปลแบบเต็ม) และ `PASSTHROUGH` (ทำให้ปกติ + แยกการใช้งาน) จัดการการบัฟเฟอร์แบบก้อน การประมาณการใช้งาน การติดตามความยาวของเนื้อหา อินสแตนซ์ตัวเข้ารหัส/ตัวถอดรหัสต่อสตรีมหลีกเลี่ยงสถานะที่ใช้ร่วมกัน | | `streamHelpers.ts` | ยูทิลิตี้ SSE ระดับต่ำ: `parseSSELine` (ทนต่อช่องว่าง), `hasValuableContent` (กรองส่วนว่างสำหรับ OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (การจัดลำดับ SSE ที่รับรู้รูปแบบด้วยการล้างข้อมูล `perf_metrics`) | | `usageTracking.ts` | การแยกการใช้โทเค็นจากรูปแบบใดๆ (Claude/OpenAI/Gemini/Responses) การประมาณค่าด้วยอัตราส่วนเครื่องมือ/ข้อความที่แยกจากกันต่ออักขระ การเพิ่มบัฟเฟอร์ (อัตราความปลอดภัยของโทเค็น 2,000 โทเค็น) การกรองฟิลด์เฉพาะรูปแบบ การบันทึกคอนโซลด้วยสี ANSI | -| `requestLogger.ts` | การบันทึกคำขอตามไฟล์ (เลือกใช้ผ่าน `ENABLE_REQUEST_LOGS=true`) สร้างโฟลเดอร์เซสชันด้วยไฟล์ที่มีหมายเลขกำกับ: `1_req_client.json` → `7_res_client.txt` I/O ทั้งหมดเป็นแบบอะซิงโครนัส (fire-and-forget) มาสก์ส่วนหัวที่ละเอียดอ่อน | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | สกัดกั้นรูปแบบเฉพาะจาก Claude CLI (การแยกชื่อ การอุ่นเครื่อง การนับ) และส่งคืนการตอบกลับปลอมโดยไม่ต้องโทรหาผู้ให้บริการใดๆ รองรับทั้งสตรีมมิ่งและไม่สตรีมมิ่ง จำกัดโดยเจตนาไว้ที่ขอบเขตของ Claude CLI | | `networkProxy.ts` | แก้ไข URL พร็อกซีขาออกสำหรับผู้ให้บริการที่กำหนดโดยมีความสำคัญ: การกำหนดค่าเฉพาะผู้ให้บริการ → การกำหนดค่าส่วนกลาง → ตัวแปรสภาพแวดล้อม (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`) รองรับการยกเว้น `NO_PROXY` กำหนดค่าแคชเป็นเวลา 30 วินาที | #### SSE Streaming Pipeline | diff --git a/docs/i18n/th/docs/TROUBLESHOOTING.md b/docs/i18n/th/docs/TROUBLESHOOTING.md index 625fd64113..ff3b96829e 100644 --- a/docs/i18n/th/docs/TROUBLESHOOTING.md +++ b/docs/i18n/th/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/th/docs/USER_GUIDE.md b/docs/i18n/th/docs/USER_GUIDE.md index 1672b34d55..dbb9111f63 100644 --- a/docs/i18n/th/docs/USER_GUIDE.md +++ b/docs/i18n/th/docs/USER_GUIDE.md @@ -468,7 +468,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -500,7 +500,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `เท็จ` | อนุญาตให้ Api Manager คัดลอกคีย์ API แบบเต็มตามต้องการ | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | จังหวะการรีเฟรชฝั่งเซิร์ฟเวอร์สำหรับข้อมูลขีดจำกัดผู้ให้บริการที่แคชไว้ ปุ่มรีเฟรช UI ยังคงทริกเกอร์การซิงค์ด้วยตนเอง | | `DISABLE_SQLITE_AUTO_BACKUP` | `เท็จ` | ปิดการใช้งานสแน็ปช็อต SQLite อัตโนมัติก่อนที่จะเขียน/นำเข้า/กู้คืน การสำรองข้อมูลด้วยตนเองยังคงใช้งานได้ | -| `ENABLE_REQUEST_LOGS` | `เท็จ` | เปิดใช้งานบันทึกคำขอ/การตอบกลับ | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `เท็จ` | บังคับใช้คุกกี้การตรวจสอบสิทธิ์ 'Secure' (หลังพร็อกซีย้อนกลับ HTTPS) | | `CLOUDFLARED_BIN` | ไม่ได้ตั้งค่า | ใช้ไบนารี 'cloudflared' ที่มีอยู่แทนการดาวน์โหลดที่ได้รับการจัดการ | | `CLOUDFLARED_PROTOCOL` | `http2` | การขนส่งสำหรับ Quick Tunnels ที่มีการจัดการ (`http2`, `quic` หรือ `auto`) | @@ -693,15 +693,15 @@ OmniRoute ใช้ความยืดหยุ่นระดับผู้ - ความไวในการตรวจจับขีด จำกัด อัตรา - พารามิเตอร์แบ็คออฟเอ็กซ์โปเนนเชียล -2.**ขีดจำกัดอัตราที่แก้ไขได้**— ค่าเริ่มต้นระดับระบบที่กำหนดค่าได้ในแดชบอร์ด: -**คำขอต่อนาที (RPM)**— คำขอสูงสุดต่อนาทีต่อบัญชี -**เวลาขั้นต่ำระหว่างคำขอ**— ช่องว่างขั้นต่ำเป็นมิลลิวินาทีระหว่างคำขอ -**คำขอพร้อมกันสูงสุด**— คำขอพร้อมกันสูงสุดต่อบัญชี + 2.**ขีดจำกัดอัตราที่แก้ไขได้**— ค่าเริ่มต้นระดับระบบที่กำหนดค่าได้ในแดชบอร์ด: -**คำขอต่อนาที (RPM)**— คำขอสูงสุดต่อนาทีต่อบัญชี -**เวลาขั้นต่ำระหว่างคำขอ**— ช่องว่างขั้นต่ำเป็นมิลลิวินาทีระหว่างคำขอ -**คำขอพร้อมกันสูงสุด**— คำขอพร้อมกันสูงสุดต่อบัญชี - คลิก**แก้ไข**เพื่อแก้ไข จากนั้น**บันทึก**หรือ**ยกเลิก**ค่ายังคงมีอยู่ผ่าน API ความยืดหยุ่น -3.**เซอร์กิตเบรกเกอร์**— ติดตามความล้มเหลวของผู้ให้บริการแต่ละราย และเปิดวงจรโดยอัตโนมัติเมื่อถึงเกณฑ์: -**ปิด**(สมบูรณ์) — คำขอดำเนินไปตามปกติ -**เปิด**— ผู้ให้บริการถูกบล็อกชั่วคราวหลังจากเกิดข้อผิดพลาดซ้ำแล้วซ้ำอีก -**HALF_OPEN**— ทดสอบว่าผู้ให้บริการฟื้นตัวหรือไม่ + 3.**เซอร์กิตเบรกเกอร์**— ติดตามความล้มเหลวของผู้ให้บริการแต่ละราย และเปิดวงจรโดยอัตโนมัติเมื่อถึงเกณฑ์: -**ปิด**(สมบูรณ์) — คำขอดำเนินไปตามปกติ -**เปิด**— ผู้ให้บริการถูกบล็อกชั่วคราวหลังจากเกิดข้อผิดพลาดซ้ำแล้วซ้ำอีก -**HALF_OPEN**— ทดสอบว่าผู้ให้บริการฟื้นตัวหรือไม่ -4.**นโยบายและตัวระบุที่ถูกล็อค**— แสดงสถานะเซอร์กิตเบรกเกอร์และตัวระบุที่ถูกล็อคพร้อมความสามารถในการบังคับปลดล็อค + 4.**นโยบายและตัวระบุที่ถูกล็อค**— แสดงสถานะเซอร์กิตเบรกเกอร์และตัวระบุที่ถูกล็อคพร้อมความสามารถในการบังคับปลดล็อค -5.**การตรวจจับขีดจำกัดอัตราอัตโนมัติ**— ตรวจสอบส่วนหัว `429` และ `Retry-After` เพื่อหลีกเลี่ยงไม่ให้เกินขีดจำกัดอัตราของผู้ให้บริการในเชิงรุก + 5.**การตรวจจับขีดจำกัดอัตราอัตโนมัติ**— ตรวจสอบส่วนหัว `429` และ `Retry-After` เพื่อหลีกเลี่ยงไม่ให้เกินขีดจำกัดอัตราของผู้ให้บริการในเชิงรุก **เคล็ดลับสำหรับมือโปร:**ใช้ปุ่ม**รีเซ็ตทั้งหมด**เพื่อล้างเซอร์กิตเบรกเกอร์และคูลดาวน์ทั้งหมดเมื่อผู้ให้บริการฟื้นตัวจากการหยุดทำงาน--- diff --git a/docs/i18n/th/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/th/docs/VM_DEPLOYMENT_GUIDE.md index 4fa114eb6b..b4cc785065 100644 --- a/docs/i18n/th/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/th/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/tr/README.md b/docs/i18n/tr/README.md index 1ce855b6ff..b49a265442 100644 --- a/docs/i18n/tr/README.md +++ b/docs/i18n/tr/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Belgeler -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/tr/docs/ARCHITECTURE.md b/docs/i18n/tr/docs/ARCHITECTURE.md index 8d7e85f741..adbb030990 100644 --- a/docs/i18n/tr/docs/ARCHITECTURE.md +++ b/docs/i18n/tr/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/tr/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/tr/docs/CODEBASE_DOCUMENTATION.md index 43a5ff2920..8e4d38e703 100644 --- a/docs/i18n/tr/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/tr/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | 'stream.ts' | **SSE Dönüşüm Akışı**— çekirdek akış hattı. İki mod: "TRANSLATE" (tam format çeviri) ve "PASSTHROUGH" (kullanımı normalleştirme + ayıklama). Parça ara belleğe almayı, kullanım tahminini ve içerik uzunluğu izlemeyi yönetir. Akış başına kodlayıcı/kod çözücü örnekleri, paylaşılan durumdan kaçınır. | | 'streamHelpers.ts' | Düşük seviyeli SSE yardımcı programları: "parseSSELine" (boşluk toleranslı), "hasValuableContent" (OpenAI/Claude/Gemini için boş parçaları filtreler), "fixInvalidId", "formatSSE" ("perf_metrics" temizliği ile formata duyarlı SSE serileştirme). | | 'usageTracking.ts' | Herhangi bir formattan (Claude/OpenAI/Gemini/Responses) jeton kullanımı çıkarma, jeton başına ayrı araç/mesaj karakter oranlarıyla tahmin, arabellek ekleme (2000 jeton güvenlik marjı), formata özel alan filtreleme, ANSI renkleriyle konsol günlüğü kaydı. | -| 'requestLogger.ts' | Dosya tabanlı istek günlüğü ('ENABLE_REQUEST_LOGS=true' aracılığıyla etkinleştirme). Numaralandırılmış dosyalarla oturum klasörleri oluşturur: `1_req_client.json` → `7_res_client.txt`. Tüm G/Ç eşzamansızdır (ateşle ve unut). Hassas başlıkları maskeler. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | 'bypassHandler.ts' | Claude CLI'den belirli kalıpları (başlık çıkarma, ısınma, sayım) yakalar ve herhangi bir sağlayıcıyı aramadan sahte yanıtlar döndürür. Hem akışı hem de akış dışını destekler. Kasıtlı olarak Claude CLI kapsamıyla sınırlıdır. | | 'ağProxy.ts' | Belirli bir sağlayıcı için giden proxy URL'sini öncelik sırasına göre çözer: sağlayıcıya özel yapılandırma → genel yapılandırma → ortam değişkenleri (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). 'NO_PROXY' hariç tutmalarını destekler. 30'lu yıllar için önbellek yapılandırması. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/tr/docs/TROUBLESHOOTING.md b/docs/i18n/tr/docs/TROUBLESHOOTING.md index 49461d553e..baa37f5861 100644 --- a/docs/i18n/tr/docs/TROUBLESHOOTING.md +++ b/docs/i18n/tr/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/tr/docs/USER_GUIDE.md b/docs/i18n/tr/docs/USER_GUIDE.md index 1b8cc01520..1326a863dd 100644 --- a/docs/i18n/tr/docs/USER_GUIDE.md +++ b/docs/i18n/tr/docs/USER_GUIDE.md @@ -467,7 +467,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -499,7 +499,7 @@ vlicense LICENSE | 'ALLOW_API_KEY_REVEAL' | 'yanlış' | API Yöneticisinin talep üzerine tam API anahtarlarını kopyalamasına izin verin | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | '70' | Önbelleğe alınan Sağlayıcı Sınırları verileri için sunucu tarafı yenileme temposu; Kullanıcı arayüzü yenileme düğmeleri hala manuel senkronizasyonu tetikliyor | | `DISABLE_SQLITE_AUTO_BACKUP` | 'yanlış' | Yazma/içe aktarma/geri yükleme öncesinde otomatik SQLite anlık görüntülerini devre dışı bırakın; manuel yedeklemeler hâlâ çalışıyor | -| `ENABLE_REQUEST_LOGS` | 'yanlış' | İstek/yanıt günlüklerini etkinleştirir | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | 'yanlış' | 'Güvenli' kimlik doğrulama çerezini zorla (HTTPS ters proxy'nin arkasında) | | `CLOUDFLARED_BIN` | ayarlanmamış | Yönetilen indirme yerine mevcut bir "cloudflared" ikili programını kullanın | | `CLOUDFLARED_PROTOCOL` | 'http2' | Yönetilen Hızlı Tüneller için Aktarım (`http2`, `quic` veya `auto`) | @@ -691,15 +691,15 @@ OmniRoute, sağlayıcı düzeyinde esnekliği dört bileşenle uygular: - Hız sınırı algılama hassasiyeti - Üstel geri çekilme parametreleri -2.**Düzenlenebilir Hız Sınırları**— Kontrol panelinde yapılandırılabilen sistem düzeyinde varsayılanlar: -**Dakika Başına İstek (RPM)**— Hesap başına dakika başına maksimum istek -**İstekler Arasındaki Minimum Süre**— İstekler arasındaki milisaniye cinsinden minimum boşluk -**Maksimum Eşzamanlı İstekler**— Hesap başına maksimum eşzamanlı istekler + 2.**Düzenlenebilir Hız Sınırları**— Kontrol panelinde yapılandırılabilen sistem düzeyinde varsayılanlar: -**Dakika Başına İstek (RPM)**— Hesap başına dakika başına maksimum istek -**İstekler Arasındaki Minimum Süre**— İstekler arasındaki milisaniye cinsinden minimum boşluk -**Maksimum Eşzamanlı İstekler**— Hesap başına maksimum eşzamanlı istekler - Değiştirmek için**Düzenle**'yi ve ardından**Kaydet**veya**İptal**'i tıklayın. Değerler, esneklik API'si aracılığıyla korunur. -3.**Devre Kesici**— Sağlayıcı başına arızaları izler ve bir eşiğe ulaşıldığında devreyi otomatik olarak açar: -**KAPALI**(Sağlıklı) — İstekler normal şekilde akıyor -**AÇIK**— Tekrarlanan hatalardan sonra sağlayıcı geçici olarak engellenir -**HALF_OPEN**— Sağlayıcının iyileşip iyileşmediği test ediliyor + 3.**Devre Kesici**— Sağlayıcı başına arızaları izler ve bir eşiğe ulaşıldığında devreyi otomatik olarak açar: -**KAPALI**(Sağlıklı) — İstekler normal şekilde akıyor -**AÇIK**— Tekrarlanan hatalardan sonra sağlayıcı geçici olarak engellenir -**HALF_OPEN**— Sağlayıcının iyileşip iyileşmediği test ediliyor -4.**İlkeler ve Kilitli Tanımlayıcılar**— Zorunlu kilit açma özelliğiyle devre kesici durumunu ve kilitli tanımlayıcıları gösterir. + 4.**İlkeler ve Kilitli Tanımlayıcılar**— Zorunlu kilit açma özelliğiyle devre kesici durumunu ve kilitli tanımlayıcıları gösterir. -5.**Otomatik Hız Sınırı Algılama**— Sağlayıcının hız sınırlarına ulaşmayı proaktif olarak önlemek için "429" ve "Sonra Yeniden Dene" başlıklarını izler. + 5.**Otomatik Hız Sınırı Algılama**— Sağlayıcının hız sınırlarına ulaşmayı proaktif olarak önlemek için "429" ve "Sonra Yeniden Dene" başlıklarını izler. **Profesyonel İpucu:**Sağlayıcı bir kesintiden kurtulduğunda tüm devre kesicileri ve bekleme sürelerini temizlemek için**Tümünü Sıfırla**düğmesini kullanın.--- diff --git a/docs/i18n/tr/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/tr/docs/VM_DEPLOYMENT_GUIDE.md index 178142ce59..95072b225c 100644 --- a/docs/i18n/tr/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/tr/docs/VM_DEPLOYMENT_GUIDE.md @@ -99,7 +99,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/uk-UA/README.md b/docs/i18n/uk-UA/README.md index 9b43547a34..643cac24e7 100644 --- a/docs/i18n/uk-UA/README.md +++ b/docs/i18n/uk-UA/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Документація -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/uk-UA/docs/ARCHITECTURE.md b/docs/i18n/uk-UA/docs/ARCHITECTURE.md index b82cb25c11..4d4a72baa4 100644 --- a/docs/i18n/uk-UA/docs/ARCHITECTURE.md +++ b/docs/i18n/uk-UA/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/uk-UA/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/uk-UA/docs/CODEBASE_DOCUMENTATION.md index aeddc571e3..7640e5d1bc 100644 --- a/docs/i18n/uk-UA/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/uk-UA/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` | **SSE Transform Stream**— основний потоковий конвеєр. Два режими: `TRANSLATE` (повноформатний переклад) і `PASSTHROUGH` (нормалізація + вилучення використання). Керується буферизацією фрагментів, оцінкою використання, відстеженням довжини вмісту. Екземпляри потокового кодера/декодера уникають спільного стану. | | `streamHelpers.ts` | Утиліти SSE низького рівня: `parseSSELine` (толерантний до пробілів), `hasValuableContent` (фільтрує порожні блоки для OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (серіалізація SSE з урахуванням формату з очищенням `perf_metrics`). | | `usageTracking.ts` | Видалення використання маркерів із будь-якого формату (Claude/OpenAI/Gemini/Responses), оцінка з окремими співвідношеннями символів на маркер для інструментів/повідомлень, додавання буфера (2000 запасів маркерів), фільтрація полів для певного формату, консольне журналювання з кольорами ANSI. | -| `requestLogger.ts` | Реєстрація запитів на основі файлів (увімкніться за допомогою `ENABLE_REQUEST_LOGS=true`). Створює папки сеансу з пронумерованими файлами: `1_req_client.json` → `7_res_client.txt`. Весь ввід-вивід є асинхронним (запустив і забув). Маскує чутливі заголовки. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Перехоплює певні шаблони від Claude CLI (вилучення заголовків, розминка, підрахунок) і повертає фальшиві відповіді без виклику жодного постачальника. Підтримує як потокове, так і не потокове. Навмисно обмежено областю CLI Claude. | | `networkProxy.ts` | Вирішує URL-адресу вихідного проксі-сервера для певного постачальника з пріоритетом: конфігурація для конкретного постачальника → глобальна конфігурація → змінні середовища (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Підтримує виключення `NO_PROXY`. Кеш конфігурації на 30 с. | #### SSE Streaming Pipeline | diff --git a/docs/i18n/uk-UA/docs/TROUBLESHOOTING.md b/docs/i18n/uk-UA/docs/TROUBLESHOOTING.md index a66e8440a7..917a82c6a9 100644 --- a/docs/i18n/uk-UA/docs/TROUBLESHOOTING.md +++ b/docs/i18n/uk-UA/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/uk-UA/docs/USER_GUIDE.md b/docs/i18n/uk-UA/docs/USER_GUIDE.md index a4cb708365..183e2f00ad 100644 --- a/docs/i18n/uk-UA/docs/USER_GUIDE.md +++ b/docs/i18n/uk-UA/docs/USER_GUIDE.md @@ -468,7 +468,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -500,7 +500,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `false` | Дозволити Api Manager копіювати повні ключі API на вимогу | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Частота оновлення на стороні сервера для кешованих даних про обмеження постачальника; Кнопки оновлення інтерфейсу досі запускають ручну синхронізацію | | `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Вимкнути автоматичні знімки SQLite перед записом/імпортом/відновленням; ручне резервне копіювання все ще працює | -| `ENABLE_REQUEST_LOGS` | `false` | Вмикає журнали запитів/відповідей | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `false` | Примусово `Secure` автентифікація cookie (за зворотним проксі HTTPS) | | `CLOUDFLARED_BIN` | не встановлено | Використовуйте існуючий двійковий файл `cloudflared` замість керованого завантаження | | `CLOUDFLARED_PROTOCOL` | `http2` | Транспорт для керованих швидких тунелів (`http2`, `quic` або `auto`) | @@ -693,15 +693,15 @@ OmniRoute реалізує стійкість на рівні постачаль - Чутливість визначення межі швидкості - Експоненціальні параметри відставання -2.**Обмеження швидкості, які можна редагувати**— параметри системного рівня, які можна налаштувати на інформаційній панелі: -**Запитів за хвилину (RPM)**— максимальна кількість запитів за хвилину на обліковий запис -**Мінімальний час між запитами**— мінімальний проміжок у мілісекундах між запитами -**Max Concurrent Requests**— максимальна кількість одночасних запитів на обліковий запис + 2.**Обмеження швидкості, які можна редагувати**— параметри системного рівня, які можна налаштувати на інформаційній панелі: -**Запитів за хвилину (RPM)**— максимальна кількість запитів за хвилину на обліковий запис -**Мінімальний час між запитами**— мінімальний проміжок у мілісекундах між запитами -**Max Concurrent Requests**— максимальна кількість одночасних запитів на обліковий запис - Натисніть**Редагувати**, щоб змінити, потім**Зберегти**або**Скасувати**. Значення зберігаються через API стійкості. -3.**Circuit Breaker**— відстежує збої кожного постачальника та автоматично розмикає ланцюг, коли досягається порогове значення: -**ЗАКРИТО**(справний) — запити надходять нормально -**OPEN**— Провайдер тимчасово заблоковано після повторних збоїв -**HALF_OPEN**— Перевірка, якщо провайдер відновився + 3.**Circuit Breaker**— відстежує збої кожного постачальника та автоматично розмикає ланцюг, коли досягається порогове значення: -**ЗАКРИТО**(справний) — запити надходять нормально -**OPEN**— Провайдер тимчасово заблоковано після повторних збоїв -**HALF_OPEN**— Перевірка, якщо провайдер відновився -4.**Політики та заблоковані ідентифікатори**— показує статус автоматичного вимикача та заблоковані ідентифікатори з можливістю примусового розблокування. + 4.**Політики та заблоковані ідентифікатори**— показує статус автоматичного вимикача та заблоковані ідентифікатори з можливістю примусового розблокування. -5.**Автовизначення ліміту швидкості**— відстежує заголовки `429` і `Retry-After`, щоб завчасно уникнути перевищення обмежень постачальника. + 5.**Автовизначення ліміту швидкості**— відстежує заголовки `429` і `Retry-After`, щоб завчасно уникнути перевищення обмежень постачальника. **Порада:**Використовуйте кнопку**Скинути все**, щоб очистити всі автоматичні вимикачі та часи відновлення, коли постачальник відновиться після збою.--- diff --git a/docs/i18n/uk-UA/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/uk-UA/docs/VM_DEPLOYMENT_GUIDE.md index 0831563f63..f93ae730c8 100644 --- a/docs/i18n/uk-UA/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/uk-UA/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/vi/README.md b/docs/i18n/vi/README.md index a71bc3f9c2..53af6319fb 100644 --- a/docs/i18n/vi/README.md +++ b/docs/i18n/vi/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## Tài liệu -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/vi/docs/ARCHITECTURE.md b/docs/i18n/vi/docs/ARCHITECTURE.md index 957da6a8b5..74ad3d19d7 100644 --- a/docs/i18n/vi/docs/ARCHITECTURE.md +++ b/docs/i18n/vi/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/vi/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/vi/docs/CODEBASE_DOCUMENTATION.md index 5b162161b5..4c845df667 100644 --- a/docs/i18n/vi/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/vi/docs/CODEBASE_DOCUMENTATION.md @@ -387,7 +387,7 @@ import "./request/claude-to-openai.js"; // ← self-registers | `stream.ts` |**SSE Transform Stream**— đường truyền phát trực tuyến cốt lõi. Hai chế độ: `TRANSLATE` (dịch định dạng đầy đủ) và `PASSTHROUGH` (bình thường hóa + trích xuất sử dụng). Xử lý việc lưu vào bộ đệm, ước tính mức sử dụng, theo dõi độ dài nội dung. Các phiên bản bộ mã hóa/giải mã mỗi luồng tránh trạng thái chia sẻ. | | `streamHelpers.ts` | Các tiện ích SSE cấp thấp: `parseSSELine` (có khả năng chịu khoảng trắng), `hasValuableContent` (lọc các đoạn trống cho OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (xê-ri hóa SSE nhận biết định dạng với tính năng dọn dẹp `perf_metrics`). | | `usageTracking.ts` | Trích xuất mức sử dụng mã thông báo từ bất kỳ định dạng nào (Claude/OpenAI/Gemini/Responses), ước tính với tỷ lệ ký tự trên mỗi mã thông báo của công cụ/thông báo riêng biệt, bổ sung bộ đệm (giới hạn an toàn 2000 mã thông báo), lọc trường theo định dạng cụ thể, ghi nhật ký bảng điều khiển với màu ANSI. | -| `requestLogger.ts` | Ghi nhật ký yêu cầu dựa trên tệp (chọn tham gia thông qua `ENABLE_REQUEST_LOGS=true`). Tạo các thư mục phiên với các tệp được đánh số: `1_req_client.json` → `7_res_client.txt`. Tất cả I/O đều không đồng bộ (bắn và quên). Mặt nạ tiêu đề nhạy cảm. | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | | `bypassHandler.ts` | Chặn các mẫu cụ thể từ Claude CLI (trích xuất tiêu đề, khởi động, đếm) và trả về các phản hồi giả mạo mà không cần gọi cho bất kỳ nhà cung cấp nào. Hỗ trợ cả phát trực tuyến và không phát trực tuyến. Cố ý giới hạn trong phạm vi Claude CLI. | | `mạngProxy.ts` | Phân giải URL proxy gửi đi cho một nhà cung cấp nhất định với mức độ ưu tiên: cấu hình dành riêng cho nhà cung cấp → cấu hình chung → biến môi trường (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Hỗ trợ loại trừ `NO_PROXY`. Cấu hình bộ nhớ đệm trong 30 giây. |#### SSE Streaming Pipeline diff --git a/docs/i18n/vi/docs/TROUBLESHOOTING.md b/docs/i18n/vi/docs/TROUBLESHOOTING.md index db673c71a4..c2c4bbe826 100644 --- a/docs/i18n/vi/docs/TROUBLESHOOTING.md +++ b/docs/i18n/vi/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/vi/docs/USER_GUIDE.md b/docs/i18n/vi/docs/USER_GUIDE.md index 277f5d9d98..c2062fccc7 100644 --- a/docs/i18n/vi/docs/USER_GUIDE.md +++ b/docs/i18n/vi/docs/USER_GUIDE.md @@ -468,7 +468,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -500,7 +500,7 @@ vlicense LICENSE | `ALLOW_API_KEY_REVEAL` | `sai` | Cho phép Api Manager sao chép toàn bộ khóa API theo yêu cầu | | `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Nhịp làm mới phía máy chủ cho dữ liệu Giới hạn nhà cung cấp được lưu trong bộ nhớ đệm; Nút làm mới giao diện người dùng vẫn kích hoạt đồng bộ hóa thủ công | | `DISABLE_SQLITE_AUTO_BACKUP` | `sai` | Vô hiệu hóa ảnh chụp nhanh SQLite tự động trước khi ghi/nhập/khôi phục; sao lưu thủ công vẫn hoạt động | -| `ENABLE_REQUEST_LOGS` | `sai` | Bật nhật ký yêu cầu/phản hồi | +| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk | | `AUTH_COOKIE_SECURE` | `sai` | Buộc cookie xác thực `Secure` (đằng sau proxy ngược HTTPS) | | `CLOUDFLARED_BIN` | bỏ đặt | Sử dụng tệp nhị phân `cloudflared` hiện có thay vì tải xuống được quản lý | | `CLOUDFLARED_PROTOCOL` | `http2` | Vận chuyển cho Đường hầm nhanh được quản lý (`http2`, `quic` hoặc `auto`) | @@ -693,15 +693,15 @@ OmniRoute triển khai khả năng phục hồi cấp nhà cung cấp với bố - Độ nhạy phát hiện giới hạn tốc độ - Thông số backoff theo cấp số nhân -2.**Giới hạn tỷ lệ có thể chỉnh sửa**— Giá trị mặc định ở cấp hệ thống có thể định cấu hình trong trang tổng quan: -**Số yêu cầu mỗi phút (RPM)**— Số yêu cầu tối đa mỗi phút cho mỗi tài khoản -**Thời gian tối thiểu giữa các yêu cầu**— Khoảng cách tối thiểu tính bằng mili giây giữa các yêu cầu -**Số yêu cầu đồng thời tối đa**— Số yêu cầu đồng thời tối đa cho mỗi tài khoản + 2.**Giới hạn tỷ lệ có thể chỉnh sửa**— Giá trị mặc định ở cấp hệ thống có thể định cấu hình trong trang tổng quan: -**Số yêu cầu mỗi phút (RPM)**— Số yêu cầu tối đa mỗi phút cho mỗi tài khoản -**Thời gian tối thiểu giữa các yêu cầu**— Khoảng cách tối thiểu tính bằng mili giây giữa các yêu cầu -**Số yêu cầu đồng thời tối đa**— Số yêu cầu đồng thời tối đa cho mỗi tài khoản - Nhấp vào**Chỉnh sửa**để sửa đổi, sau đó nhấp vào**Lưu**hoặc**Hủy**. Các giá trị vẫn tồn tại thông qua API khả năng phục hồi. -3.**Bộ ngắt mạch**— Theo dõi lỗi của mỗi nhà cung cấp và tự động mở mạch khi đạt đến ngưỡng: -**ĐÃ ĐÓNG**(Khỏe mạnh) — Yêu cầu diễn ra bình thường -**OPEN**— Nhà cung cấp bị chặn tạm thời sau nhiều lần thất bại -**HALF_OPEN**— Kiểm tra xem nhà cung cấp đã phục hồi chưa + 3.**Bộ ngắt mạch**— Theo dõi lỗi của mỗi nhà cung cấp và tự động mở mạch khi đạt đến ngưỡng: -**ĐÃ ĐÓNG**(Khỏe mạnh) — Yêu cầu diễn ra bình thường -**OPEN**— Nhà cung cấp bị chặn tạm thời sau nhiều lần thất bại -**HALF_OPEN**— Kiểm tra xem nhà cung cấp đã phục hồi chưa -4.**Chính sách & Mã định danh bị khóa**— Hiển thị trạng thái cầu dao và mã định danh bị khóa với khả năng buộc mở khóa. + 4.**Chính sách & Mã định danh bị khóa**— Hiển thị trạng thái cầu dao và mã định danh bị khóa với khả năng buộc mở khóa. -5.**Tự động phát hiện giới hạn tốc độ**— Giám sát tiêu đề `429` và `Thử lại sau` để chủ động tránh đạt giới hạn tốc độ của nhà cung cấp. + 5.**Tự động phát hiện giới hạn tốc độ**— Giám sát tiêu đề `429` và `Thử lại sau` để chủ động tránh đạt giới hạn tốc độ của nhà cung cấp. **Mẹo chuyên nghiệp:**Sử dụng nút**Đặt lại tất cả**để xóa tất cả cầu dao và thời gian hồi chiêu khi nhà cung cấp khôi phục sau khi ngừng hoạt động.--- diff --git a/docs/i18n/vi/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/vi/docs/VM_DEPLOYMENT_GUIDE.md index 1b60862add..36fefc10cc 100644 --- a/docs/i18n/vi/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/vi/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/i18n/zh-CN/README.md b/docs/i18n/zh-CN/README.md index 2fa06c9ccf..9c35c398a6 100644 --- a/docs/i18n/zh-CN/README.md +++ b/docs/i18n/zh-CN/README.md @@ -4,7 +4,6 @@ --- - ### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback. _Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._ @@ -959,7 +958,7 @@ do_install() { #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -1313,13 +1312,13 @@ OmniRoute v3.5 is built as an operational platform, not just a relay proxy. ### 🆕 New — v3.5.5 Highlights (Apr 2026) -| Feature | What It Does | -| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | -| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | -| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | -| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | -| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | +| Feature | What It Does | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| 🔗 **Context Relay Strategy** | New combo strategy that preserves session continuity via structured handoff summaries when accounts rotate mid-conversation | +| 🛡️ **Proxy Hardening** | Token health check, API key validation, and undici dispatcher all honor proxy config — no more bypass in restricted envs | +| ⚠️ **Node.js 24 Login Warning** | Login page proactively detects incompatible Node.js versions and shows a clear warning banner with instructions | +| 📎 **Gemini PDF Attachments** | PDF files attached in chat messages are now correctly routed to Gemini via `inline_data` and generic base64 detection | +| 🔒 **CodeQL Security Hardening** | Resolved SSRF, insecure randomness, polynomial ReDoS, and incomplete URL sanitization alerts | ### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026) @@ -2195,22 +2194,22 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux ## 文档 -| Document | Description | -| ---------------------------------------------- | --------------------------------------------------- | -| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | -| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | -| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | -| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | -| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | -| [Context Relay](docs/features/context-relay.md)| Session handoff strategy for account rotation | -| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | -| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | -| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | -| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | -| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | -| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | -| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | -| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | +| Document | Description | +| ----------------------------------------------- | --------------------------------------------------- | +| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment | +| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples | +| [MCP Server](open-sse/mcp-server/README.md) | 25 MCP tools, IDE configs, Python/TS/Go clients | +| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt | +| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing | +| [Context Relay](docs/features/context-relay.md) | Session handoff strategy for account rotation | +| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions | +| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals | +| [Contributing](CONTRIBUTING.md) | Development setup and guidelines | +| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification | +| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices | +| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup | +| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots | +| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps | --- diff --git a/docs/i18n/zh-CN/docs/ARCHITECTURE.md b/docs/i18n/zh-CN/docs/ARCHITECTURE.md index ae37a17758..180298a698 100644 --- a/docs/i18n/zh-CN/docs/ARCHITECTURE.md +++ b/docs/i18n/zh-CN/docs/ARCHITECTURE.md @@ -4,8 +4,6 @@ --- - - _Last updated: 2026-03-28_ ## Executive Summary @@ -717,16 +715,14 @@ Additional processing layers in the translation pipeline: The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`. -## Request Logger Pipeline +## Request Logging and Artifacts -The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`: +The older file-based request logger (`open-sse/utils/requestLogger.ts`) is retained only for +legacy compatibility. The current runtime contract uses: -``` -1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json -→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt -``` - -Files are written to `<repo>/logs/<session>/` for each request session. +- `APP_LOG_TO_FILE=true` for application and audit logs written under `<repo>/logs/` +- SQLite-backed call log records in `call_logs` +- `${DATA_DIR}/call_logs/YYYY-MM-DD/...` artifacts when the call log pipeline is enabled ## Failure Modes and Resilience @@ -765,7 +761,8 @@ Runtime visibility sources: - per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`) - four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true` - textual request status log in `log.txt` (optional/compat) -- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true` +- optional application log files under `logs/` when `APP_LOG_TO_FILE=true` +- optional request artifacts under `${DATA_DIR}/call_logs/` when the call log pipeline is enabled - dashboard usage endpoints (`/api/usage/*`) for UI consumption Detailed request payload capture stores up to four JSON payload stages per routed call: @@ -792,7 +789,7 @@ Environment variables actively used by code: - Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` - Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME` - Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT` -- Logging: `ENABLE_REQUEST_LOGS` +- Logging: `APP_LOG_TO_FILE`, `APP_LOG_RETENTION_DAYS`, `CALL_LOG_RETENTION_DAYS` - Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL` - Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants - SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` diff --git a/docs/i18n/zh-CN/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/zh-CN/docs/CODEBASE_DOCUMENTATION.md index d75be900ca..79c5471ba0 100644 --- a/docs/i18n/zh-CN/docs/CODEBASE_DOCUMENTATION.md +++ b/docs/i18n/zh-CN/docs/CODEBASE_DOCUMENTATION.md @@ -381,15 +381,15 @@ import "./request/claude-to-openai.js"; // ← self-registers ### 4.6 Utils (`open-sse/utils/`) -| 文件 | 目的 | -| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | -| `错误.ts` | 错误响应构建(OpenAI 兼容格式)、上游错误解析、从错误消息中提取反重力重试时间、SSE 错误流。 | -| `stream.ts` | **SSE Transform Stream**— 核心流管道。两种模式:“TRANSLATE”(完整格式翻译)和“PASSTHROUGH”(规范化+提取使用)。处理块缓冲、使用情况估计、内容长度跟踪。每个流编码器/解码器实例避免共享状态。 | -| `streamHelpers.ts` | 低级 SSE 实用程序:“parseSSELine”(容忍空格)、“hasValuableContent”(过滤 OpenAI/Claude/Gemini 的空块)、“fixInvalidId”、“formatSSE”(具有“perf_metrics”清理功能的格式感知 SSE 序列化)。 | -| `usageTracking.ts` | 从任何格式(Claude/OpenAI/Gemini/Responses)提取令牌使用情况,使用单独的工具/消息字符/令牌比率进行估计,缓冲区添加(2000 个令牌安全裕度),特定于格式的字段过滤,使用 ANSI 颜色的控制台日志记录。 | -| `requestLogger.ts` | 基于文件的请求日志记录(通过“ENABLE_REQUEST_LOGS=true”选择加入)。创建包含编号文件的会话文件夹:“1_req_client.json”→“7_res_client.txt”。所有 I/O 都是异步的(即发即弃)。屏蔽敏感标头。 | -| `bypassHandler.ts` | 拦截来自 Claude CLI 的特定模式(标题提取、预热、计数)并返回虚假响应,而无需调用任何提供者。支持流式和非流式。有意限制于 Claude CLI 范围。 | -| `networkProxy.ts` | 优先解析给定提供商的出站代理 URL:特定于提供商的配置 → 全局配置 → 环境变量 (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`)。支持“NO_PROXY”排除。缓存配置 30 秒。 | #### SSE Streaming Pipeline | +| 文件 | 目的 | +| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | +| `错误.ts` | 错误响应构建(OpenAI 兼容格式)、上游错误解析、从错误消息中提取反重力重试时间、SSE 错误流。 | +| `stream.ts` | **SSE Transform Stream**— 核心流管道。两种模式:“TRANSLATE”(完整格式翻译)和“PASSTHROUGH”(规范化+提取使用)。处理块缓冲、使用情况估计、内容长度跟踪。每个流编码器/解码器实例避免共享状态。 | +| `streamHelpers.ts` | 低级 SSE 实用程序:“parseSSELine”(容忍空格)、“hasValuableContent”(过滤 OpenAI/Claude/Gemini 的空块)、“fixInvalidId”、“formatSSE”(具有“perf_metrics”清理功能的格式感知 SSE 序列化)。 | +| `usageTracking.ts` | 从任何格式(Claude/OpenAI/Gemini/Responses)提取令牌使用情况,使用单独的工具/消息字符/令牌比率进行估计,缓冲区添加(2000 个令牌安全裕度),特定于格式的字段过滤,使用 ANSI 颜色的控制台日志记录。 | +| `requestLogger.ts` | Legacy file-based request logging helper kept for compatibility. Current deployments should prefer `APP_LOG_TO_FILE` for application logs and the call log pipeline for persisted request artifacts. | +| `bypassHandler.ts` | 拦截来自 Claude CLI 的特定模式(标题提取、预热、计数)并返回虚假响应,而无需调用任何提供者。支持流式和非流式。有意限制于 Claude CLI 范围。 | +| `networkProxy.ts` | 优先解析给定提供商的出站代理 URL:特定于提供商的配置 → 全局配置 → 环境变量 (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`)。支持“NO_PROXY”排除。缓存配置 30 秒。 | #### SSE Streaming Pipeline | ```mermaid flowchart TD diff --git a/docs/i18n/zh-CN/docs/TROUBLESHOOTING.md b/docs/i18n/zh-CN/docs/TROUBLESHOOTING.md index d9aaae4b22..02fb5aea6f 100644 --- a/docs/i18n/zh-CN/docs/TROUBLESHOOTING.md +++ b/docs/i18n/zh-CN/docs/TROUBLESHOOTING.md @@ -4,22 +4,20 @@ --- - - Common problems and solutions for OmniRoute. --- ## 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 request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` | -| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` | -| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) | -| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | +| 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 v1.4.11+ (Zod schema fix for settings persistence) | +| Login crash / blank page | You may be on Node.js 24+ — see [Node.js Compatibility](#nodejs-compatibility) below | | Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below | --- @@ -33,6 +31,7 @@ Common problems and solutions for OmniRoute. **Cause:** You are running Node.js 24+. The `better-sqlite3` native binary is not compatible with Node.js 24, which causes a fatal crash when the server tries to initialize the database. **Symptoms:** + - Login page shows a blank screen or a server error - Console shows `Error: Module did not self-register` or similar native binding errors - Starting with v3.5.5, the login page shows an **orange warning banner** with your Node version if incompatibility is detected @@ -162,9 +161,11 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed, ## Debugging -### Enable Request Logs +### Enable Log Files -Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory. +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. ### Check Provider Health @@ -179,8 +180,9 @@ 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}/log.txt` and `${DATA_DIR}/call_logs/` -- Request logs: `<repo>/logs/...` (when `ENABLE_REQUEST_LOGS=true`) +- 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 --- diff --git a/docs/i18n/zh-CN/docs/USER_GUIDE.md b/docs/i18n/zh-CN/docs/USER_GUIDE.md index ea8dd566f7..1cef41e5cf 100644 --- a/docs/i18n/zh-CN/docs/USER_GUIDE.md +++ b/docs/i18n/zh-CN/docs/USER_GUIDE.md @@ -464,7 +464,7 @@ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone #!/bin/sh export PORT="${PORT:-20128}" export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}" -export LOG_TO_FILE="${LOG_TO_FILE:-false}" +export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}" mkdir -p "${DATA_DIR}" exec node /usr/lib/omniroute/.next/standalone/server.js "$@" EOF @@ -688,15 +688,15 @@ OmniRoute 通过四个组件实现提供商级弹性: - 速率限制检测灵敏度 - 指数退避参数 -2.**可编辑的速率限制**— 可在仪表板中配置的系统级默认值:-**每分钟请求数 (RPM)**— 每个帐户每分钟最大请求数 -**请求之间的最小时间**— 请求之间的最小间隔(以毫秒为单位)-**最大并发请求**— 每个帐户的最大并发请求数 + 2.**可编辑的速率限制**— 可在仪表板中配置的系统级默认值:-**每分钟请求数 (RPM)**— 每个帐户每分钟最大请求数 -**请求之间的最小时间**— 请求之间的最小间隔(以毫秒为单位)-**最大并发请求**— 每个帐户的最大并发请求数 - 点击**编辑**进行修改,然后点击**保存**或**取消**。价值通过弹性 API 得以保留。 -3.**断路器**— 跟踪每个提供商的故障并在达到阈值时自动打开电路:-**CLOSED**(健康)— 请求正常流动 -**OPEN**— 提供商在多次失败后被暂时阻止 -**HALF_OPEN**— 测试提供商是否已恢复 + 3.**断路器**— 跟踪每个提供商的故障并在达到阈值时自动打开电路:-**CLOSED**(健康)— 请求正常流动 -**OPEN**— 提供商在多次失败后被暂时阻止 -**HALF_OPEN**— 测试提供商是否已恢复 -4.**策略和锁定标识符**— 显示断路器状态和具有强制解锁功能的锁定标识符。 + 4.**策略和锁定标识符**— 显示断路器状态和具有强制解锁功能的锁定标识符。 -5.**速率限制自动检测**— 监控“429”和“Retry-After”标头,以主动避免达到提供商速率限制。 + 5.**速率限制自动检测**— 监控“429”和“Retry-After”标头,以主动避免达到提供商速率限制。 **专业提示:**当提供商从中断中恢复时,使用**全部重置**按钮可以清除所有断路器和冷却时间。--- diff --git a/docs/i18n/zh-CN/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/zh-CN/docs/VM_DEPLOYMENT_GUIDE.md index 8f598bc9e7..b1b61d1059 100644 --- a/docs/i18n/zh-CN/docs/VM_DEPLOYMENT_GUIDE.md +++ b/docs/i18n/zh-CN/docs/VM_DEPLOYMENT_GUIDE.md @@ -100,7 +100,7 @@ NODE_ENV=production HOSTNAME=0.0.0.0 DATA_DIR=/app/data STORAGE_DRIVER=sqlite -ENABLE_REQUEST_LOGS=true +APP_LOG_TO_FILE=true AUTH_COOKIE_SECURE=false REQUIRE_API_KEY=false diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 71309f6ce4..9f047f3b16 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: title: OmniRoute API - version: 3.5.5 + version: 3.5.6 description: | OmniRoute is a local-first AI API proxy router. It provides an OpenAI-compatible endpoint that routes requests to multiple AI providers with load balancing, diff --git a/electron/package.json b/electron/package.json index 8ff6c7483b..de6154dbd7 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,6 +1,6 @@ { "name": "omniroute-desktop", - "version": "3.5.5", + "version": "3.5.6", "description": "OmniRoute Desktop Application", "main": "main.js", "author": { diff --git a/llm.txt b/llm.txt index c071f606d8..50aa9537ea 100644 --- a/llm.txt +++ b/llm.txt @@ -8,7 +8,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo **Key value:** One endpoint (`http://localhost:20128/v1`), unlimited models, zero downtime, minimal cost. -**Current version:** 3.5.5 +**Current version:** 3.5.6 ## Tech Stack @@ -279,7 +279,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo └── .env.example # Environment variable template ``` -## Key Features (v3.5.5) +## Key Features (v3.5.6) ### Core Proxy - **60+ AI providers** with automatic format translation diff --git a/open-sse/config/embeddingRegistry.ts b/open-sse/config/embeddingRegistry.ts index 6cf867df0f..1b9b6ebfd9 100644 --- a/open-sse/config/embeddingRegistry.ts +++ b/open-sse/config/embeddingRegistry.ts @@ -102,6 +102,29 @@ export const EMBEDDING_PROVIDERS: Record<string, EmbeddingProvider> = { authHeader: "bearer", models: [{ id: "nvidia/nv-embedqa-e5-v5", name: "NV EmbedQA E5 v5", dimensions: 1024 }], }, + + openrouter: { + id: "openrouter", + baseUrl: "https://openrouter.ai/api/v1/embeddings", + authType: "apikey", + authHeader: "bearer", + models: [ + { id: "openai/text-embedding-3-small", name: "Text Embedding 3 Small (OpenRouter)", dimensions: 1536 }, + { id: "openai/text-embedding-3-large", name: "Text Embedding 3 Large (OpenRouter)", dimensions: 3072 }, + { id: "openai/text-embedding-ada-002", name: "Text Embedding Ada 002 (OpenRouter)", dimensions: 1536 }, + ], + }, + + github: { + id: "github", + baseUrl: "https://models.inference.ai.azure.com/embeddings", + authType: "apikey", + authHeader: "bearer", + models: [ + { id: "text-embedding-3-small", name: "Text Embedding 3 Small (GitHub)", dimensions: 1536 }, + { id: "text-embedding-3-large", name: "Text Embedding 3 Large (GitHub)", dimensions: 3072 }, + ], + }, }; /** diff --git a/open-sse/config/imageRegistry.ts b/open-sse/config/imageRegistry.ts index 85ffcd57d9..484987d735 100644 --- a/open-sse/config/imageRegistry.ts +++ b/open-sse/config/imageRegistry.ts @@ -135,6 +135,21 @@ export const IMAGE_PROVIDERS = { ], supportedSizes: ["512x512", "768x768", "1024x1024"], }, + + openrouter: { + id: "openrouter", + baseUrl: "https://openrouter.ai/api/v1/images/generations", + authType: "apikey", + authHeader: "bearer", + format: "openai", + models: [ + { id: "openai/dall-e-3", name: "DALL-E 3 (via OpenRouter)" }, + { id: "openai/gpt-image-1", name: "GPT Image 1 (via OpenRouter)" }, + { id: "google/imagen-3.0-generate-002", name: "Imagen 3 (via OpenRouter)" }, + { id: "black-forest-labs/FLUX.1-schnell", name: "FLUX.1 Schnell (via OpenRouter)" }, + ], + supportedSizes: ["1024x1024", "1024x1792", "1792x1024", "256x256", "512x512"], + }, }; /** diff --git a/open-sse/config/providerRegistry.ts b/open-sse/config/providerRegistry.ts index f3875c97b8..f456aa7d2c 100644 --- a/open-sse/config/providerRegistry.ts +++ b/open-sse/config/providerRegistry.ts @@ -161,7 +161,7 @@ export const REGISTRY: Record<string, RegistryEntry> = { }, oauth: { clientIdEnv: "CLAUDE_OAUTH_CLIENT_ID", - clientIdDefault: "9d1c250a-e61b-44d9-88ed-5944d1962f5e", + clientIdDefault: "", tokenUrl: "https://console.anthropic.com/v1/oauth/token", }, models: [ @@ -188,9 +188,9 @@ export const REGISTRY: Record<string, RegistryEntry> = { defaultContextLength: 1048576, oauth: { clientIdEnv: "GEMINI_OAUTH_CLIENT_ID", - clientIdDefault: "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com", + clientIdDefault: "", clientSecretEnv: "GEMINI_OAUTH_CLIENT_SECRET", - clientSecretDefault: "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", + clientSecretDefault: "", }, models: [], // Models are populated from Google's API via sync-models (per API key). @@ -212,9 +212,9 @@ export const REGISTRY: Record<string, RegistryEntry> = { defaultContextLength: 1048576, oauth: { clientIdEnv: "GEMINI_CLI_OAUTH_CLIENT_ID", - clientIdDefault: "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com", - clientSecretEnv: "GEMINI_OAUTH_CLIENT_SECRET", - clientSecretDefault: "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", + clientIdDefault: "", + clientSecretEnv: "GEMINI_CLI_OAUTH_CLIENT_SECRET", + clientSecretDefault: "", }, models: [ { id: "gemini-3-pro-preview", name: "Gemini 3 Pro Preview" }, @@ -244,7 +244,7 @@ export const REGISTRY: Record<string, RegistryEntry> = { }, oauth: { clientIdEnv: "CODEX_OAUTH_CLIENT_ID", - clientIdDefault: "app_EMoamEEZ73f0CkXaXp7hrann", + clientIdDefault: "", clientSecretEnv: "CODEX_OAUTH_CLIENT_SECRET", clientSecretDefault: "", tokenUrl: "https://auth.openai.com/oauth/token", @@ -295,7 +295,7 @@ export const REGISTRY: Record<string, RegistryEntry> = { }, oauth: { clientIdEnv: "QWEN_OAUTH_CLIENT_ID", - clientIdDefault: "f0304373b74a44d2b584a3fb70ca9e56", + clientIdDefault: "", tokenUrl: "https://chat.qwen.ai/api/v1/oauth2/token", authUrl: "https://chat.qwen.ai/api/v1/oauth2/device/code", }, @@ -365,9 +365,9 @@ export const REGISTRY: Record<string, RegistryEntry> = { }, oauth: { clientIdEnv: "ANTIGRAVITY_OAUTH_CLIENT_ID", - clientIdDefault: "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com", + clientIdDefault: "", clientSecretEnv: "ANTIGRAVITY_OAUTH_CLIENT_SECRET", - clientSecretDefault: "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", + clientSecretDefault: "", }, models: [ { id: "claude-opus-4-6-thinking", name: "Claude Opus 4.6 Thinking" }, @@ -695,7 +695,7 @@ export const REGISTRY: Record<string, RegistryEntry> = { authType: "oauth", oauth: { clientIdEnv: "KIMI_CODING_OAUTH_CLIENT_ID", - clientIdDefault: "17e5f671-d194-4dfb-9706-5516cb48c098", + clientIdDefault: "", tokenUrl: "https://auth.kimi.com/api/oauth/token", refreshUrl: "https://auth.kimi.com/api/oauth/token", authUrl: "https://auth.kimi.com/api/oauth/device_authorization", @@ -792,7 +792,7 @@ export const REGISTRY: Record<string, RegistryEntry> = { baseUrl: "https://api.minimax.io/anthropic/v1/messages", urlSuffix: "?beta=true", authType: "apikey", - authHeader: "x-api-key", + authHeader: "bearer", headers: { "Anthropic-Version": "2023-06-01", "Anthropic-Beta": "claude-code-20250219,interleaved-thinking-2025-05-14", @@ -816,7 +816,7 @@ export const REGISTRY: Record<string, RegistryEntry> = { baseUrl: "https://api.minimaxi.com/anthropic/v1/messages", urlSuffix: "?beta=true", authType: "apikey", - authHeader: "x-api-key", + authHeader: "bearer", headers: { "Anthropic-Version": "2023-06-01", "Anthropic-Beta": "claude-code-20250219,interleaved-thinking-2025-05-14", diff --git a/open-sse/executors/default.ts b/open-sse/executors/default.ts index 2e7d1b2896..1d57ac8515 100644 --- a/open-sse/executors/default.ts +++ b/open-sse/executors/default.ts @@ -87,8 +87,6 @@ export class DefaultExecutor extends BaseExecutor { case "kimi-coding": case "bailian-coding-plan": case "kimi-coding-apikey": - case "minimax": - case "minimax-cn": headers["x-api-key"] = effectiveKey || credentials.accessToken; break; default: diff --git a/open-sse/executors/qoder.ts b/open-sse/executors/qoder.ts index 77139b821f..26e1889245 100644 --- a/open-sse/executors/qoder.ts +++ b/open-sse/executors/qoder.ts @@ -16,6 +16,9 @@ function getAuthToken(credentials: ProviderCredentials): string { if (typeof credentials.refreshToken === "string" && credentials.refreshToken.trim()) { return credentials.refreshToken.trim(); } + // Fallback: QODER_PERSONAL_ACCESS_TOKEN env var (#966) + const envToken = String(process.env.QODER_PERSONAL_ACCESS_TOKEN || "").trim(); + if (envToken) return envToken; return ""; } diff --git a/open-sse/mcp-server/server.ts b/open-sse/mcp-server/server.ts index 6b39075b01..7442d91e04 100644 --- a/open-sse/mcp-server/server.ts +++ b/open-sse/mcp-server/server.ts @@ -59,10 +59,11 @@ import { import { memoryTools } from "./tools/memoryTools.ts"; import { skillTools } from "./tools/skillTools.ts"; import { normalizeQuotaResponse } from "../../src/shared/contracts/quota.ts"; +import { resolveOmniRouteBaseUrl } from "../../src/shared/utils/resolveOmniRouteBaseUrl.ts"; // ============ Configuration ============ -const OMNIROUTE_BASE_URL = process.env.OMNIROUTE_BASE_URL || "http://localhost:20128"; +const OMNIROUTE_BASE_URL = resolveOmniRouteBaseUrl(); const OMNIROUTE_API_KEY = process.env.OMNIROUTE_API_KEY || ""; const MCP_ENFORCE_SCOPES = process.env.OMNIROUTE_MCP_ENFORCE_SCOPES === "true"; const MCP_ALLOWED_SCOPES = new Set( diff --git a/open-sse/mcp-server/tools/advancedTools.ts b/open-sse/mcp-server/tools/advancedTools.ts index 781e50ac68..30c356a468 100644 --- a/open-sse/mcp-server/tools/advancedTools.ts +++ b/open-sse/mcp-server/tools/advancedTools.ts @@ -17,8 +17,9 @@ import { logToolCall } from "../audit.ts"; import { normalizeQuotaResponse } from "../../../src/shared/contracts/quota.ts"; +import { resolveOmniRouteBaseUrl } from "../../../src/shared/utils/resolveOmniRouteBaseUrl.ts"; -const OMNIROUTE_BASE_URL = process.env.OMNIROUTE_BASE_URL || "http://localhost:20128"; +const OMNIROUTE_BASE_URL = resolveOmniRouteBaseUrl(); const OMNIROUTE_API_KEY = process.env.OMNIROUTE_API_KEY || ""; async function apiFetch(path: string, options: RequestInit = {}): Promise<unknown> { diff --git a/open-sse/package.json b/open-sse/package.json index cd0e61f414..46b73cf4a3 100644 --- a/open-sse/package.json +++ b/open-sse/package.json @@ -1,6 +1,6 @@ { "name": "@omniroute/open-sse", - "version": "3.5.5", + "version": "3.5.6", "description": "Express SSE sidecar for OmniRoute — handles streaming, protocol translation, and provider orchestration", "type": "module", "main": "index.js", diff --git a/open-sse/services/qoderCli.ts b/open-sse/services/qoderCli.ts index ca8e7be1a2..0add5d0dd1 100644 --- a/open-sse/services/qoderCli.ts +++ b/open-sse/services/qoderCli.ts @@ -400,6 +400,31 @@ export async function validateQoderCliPat({ apiKey: string; providerSpecificData?: JsonRecord; }) { + // Resolve token: dashboard input → env var fallback + const resolvedToken = apiKey?.trim() || String(process.env.QODER_PERSONAL_ACCESS_TOKEN || "").trim(); + + if (!resolvedToken) { + return { + valid: false, + error: + "No Qoder token provided. Get your Personal Access Token from https://qoder.com/account/integrations or set QODER_PERSONAL_ACCESS_TOKEN env var.", + unsupported: false, + }; + } + + // PAT format guidance: Qoder PATs should be non-empty strings. + // Warn if the token looks like it might be an encrypted blob (from ~/.qoder/.auth/user) + // rather than a proper PAT from the website. + if (resolvedToken.length > 500) { + return { + valid: false, + error: + "Token appears to be an encrypted auth blob (from ~/.qoder/.auth/user). " + + "Please use a Personal Access Token from https://qoder.com/account/integrations instead.", + unsupported: false, + }; + } + const modelId = getString(providerSpecificData.validationModelId).trim() || getString(providerSpecificData.modelId).trim() || @@ -411,7 +436,32 @@ export async function validateQoderCliPat({ stream: false, }); - const headers = buildCosyHeadersForValidation(bodyStr, apiKey); + // Step 1: Connectivity check — verify Qoder API is reachable + try { + const pingRes = await fetch("https://api1.qoder.sh/algo/api/v1/ping", { + method: "GET", + // @ts-ignore + signal: AbortSignal.timeout(10000), + }); + if (!pingRes.ok) { + return { + valid: false, + error: `Qoder API unreachable (ping returned ${pingRes.status}). Check your network/proxy configuration.`, + unsupported: false, + }; + } + } catch (pingErr: any) { + return { + valid: false, + error: + `Cannot reach Qoder API (${pingErr.message}). ` + + "If behind a proxy, configure HTTPS_PROXY. For Docker, ensure the container has internet access.", + unsupported: false, + }; + } + + // Step 2: Auth validation — send a minimal request with the PAT + const headers = buildCosyHeadersForValidation(bodyStr, resolvedToken); const endpoint = "https://api1.qoder.sh/algo/api/v2/service/pro/sse/agent_chat_generation?AgentId=agent_common"; @@ -423,11 +473,45 @@ export async function validateQoderCliPat({ // @ts-ignore signal: AbortSignal.timeout(30000), }); - if (!res.ok) { - return { valid: false, error: `HTTP ${res.status}: ${await res.text()}`, unsupported: false }; + + if (res.ok || res.status === 200) { + return { valid: true, error: null, unsupported: false }; } - return { valid: true, error: null, unsupported: false }; + + // Parse error body for better diagnostics + let errorDetail = ""; + try { + const errBody = await res.text(); + errorDetail = errBody.slice(0, 300); + } catch {} + + if (res.status === 401 || res.status === 403) { + return { + valid: false, + error: + `Authentication failed (HTTP ${res.status}). ` + + "Make sure you're using a valid Personal Access Token from https://qoder.com/account/integrations. " + + "Note: tokens from ~/.qoder/.auth/user are encrypted and cannot be used directly." + + (errorDetail ? ` Server: ${errorDetail}` : ""), + unsupported: false, + }; + } + + // 4xx other than auth — token was accepted but request had issues (model, format, etc.) + if (res.status >= 400 && res.status < 500) { + return { valid: true, error: null, unsupported: false }; + } + + return { + valid: false, + error: `Qoder API returned HTTP ${res.status}${errorDetail ? `: ${errorDetail}` : ""}`, + unsupported: false, + }; } catch (e: any) { - return { valid: false, error: e.message, unsupported: false }; + return { + valid: false, + error: `Qoder validation request failed: ${e.message}`, + unsupported: false, + }; } } diff --git a/open-sse/translator/request/openai-to-claude.ts b/open-sse/translator/request/openai-to-claude.ts index 1d20eac08a..b2850de7b5 100644 --- a/open-sse/translator/request/openai-to-claude.ts +++ b/open-sse/translator/request/openai-to-claude.ts @@ -488,7 +488,19 @@ function getContentBlocksFromMessage(msg, toolNameMap = new Map(), disableToolPr // Convert OpenAI tool choice to Claude format function convertOpenAIToolChoice(choice) { if (!choice) return { type: "auto" }; - if (typeof choice === "object" && choice.type) return choice; + if (typeof choice === "object" && choice.type) { + // OpenAI sends {type: "function", function: {name}} — convert to Claude {type: "tool", name} + if (choice.type === "function" && choice.function?.name) { + return { type: "tool", name: choice.function.name }; + } + // Map OpenAI string types to Claude equivalents + if (choice.type === "auto" || choice.type === "none") return { type: "auto" }; + if (choice.type === "required" || choice.type === "any") return { type: CLAUDE_TOOL_CHOICE_REQUIRED }; + // If type is "tool" already (Claude-native), pass through + if (choice.type === "tool" && choice.name) return choice; + // Fallback: unknown object type — default to auto to avoid 400 errors + return { type: "auto" }; + } if (choice === "auto" || choice === "none") return { type: "auto" }; if (choice === "required") return { type: CLAUDE_TOOL_CHOICE_REQUIRED }; if (typeof choice === "object" && choice.function) { diff --git a/open-sse/utils/proxyFetch.ts b/open-sse/utils/proxyFetch.ts index 007907d40c..ff0a2de58a 100644 --- a/open-sse/utils/proxyFetch.ts +++ b/open-sse/utils/proxyFetch.ts @@ -198,10 +198,22 @@ async function patchedFetch(input: RequestInfo | URL, options: FetchWithDispatch if (store) store.used = false; } } - return (undiciFetch as unknown as (...args: unknown[]) => Promise<Response>)(input, { - ...options, - dispatcher: getDefaultDispatcher(), - }); + // Direct connection (no proxy) — use undici with custom dispatcher for timeout control. + // Falls back to original native fetch if dispatcher initialization fails (#1054). + try { + return await (undiciFetch as unknown as (...args: unknown[]) => Promise<Response>)(input, { + ...options, + dispatcher: getDefaultDispatcher(), + }); + } catch (dispatcherError) { + const msg = dispatcherError instanceof Error ? dispatcherError.message : String(dispatcherError); + // Only fallback for connection/dispatcher errors, not HTTP errors + if (msg.includes("fetch failed") || msg.includes("ECONNREFUSED") || msg.includes("UND_ERR")) { + console.warn(`[ProxyFetch] Undici dispatcher failed, falling back to native fetch: ${msg}`); + return originalFetchWithDispatcher(input, options); + } + throw dispatcherError; + } } try { diff --git a/package-lock.json b/package-lock.json index cf07955fb3..bef39a4d69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "omniroute", - "version": "3.5.4", + "version": "3.5.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "omniroute", - "version": "3.5.4", + "version": "3.5.6", "hasInstallScript": true, "license": "MIT", "workspaces": [ @@ -29,7 +29,7 @@ "js-yaml": "^4.1.0", "lowdb": "^7.0.1", "monaco-editor": "^0.55.1", - "next": "^16.2.2", + "next": "^16.2.3", "next-intl": "^4.8.3", "node-machine-id": "^1.1.12", "open": "^11.0.0", @@ -2797,9 +2797,9 @@ } }, "node_modules/@next/env": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.2.tgz", - "integrity": "sha512-LqSGz5+xGk9EL/iBDr2yo/CgNQV6cFsNhRR2xhSXYh7B/hb4nePCxlmDvGEKG30NMHDFf0raqSyOZiQrO7BkHQ==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.3.tgz", + "integrity": "sha512-ZWXyj4uNu4GCWQw9cjRxWlbD+33mcDszIo9iQxFnBX3Wmgq9ulaSJcl6VhuWx5pCWqqD+9W6Wfz7N0lM5lYPMA==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -2813,9 +2813,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.2.tgz", - "integrity": "sha512-B92G3ulrwmkDSEJEp9+XzGLex5wC1knrmCSIylyVeiAtCIfvEJYiN3v5kXPlYt5R4RFlsfO/v++aKV63Acrugg==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.3.tgz", + "integrity": "sha512-u37KDKTKQ+OQLvY+z7SNXixwo4Q2/IAJFDzU1fYe66IbCE51aDSAzkNDkWmLN0yjTUh4BKBd+hb69jYn6qqqSg==", "cpu": [ "arm64" ], @@ -2829,9 +2829,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.2.tgz", - "integrity": "sha512-7ZwSgNKJNQiwW0CKhNm9B1WS2L1Olc4B2XY0hPYCAL3epFnugMhuw5TMWzMilQ3QCZcCHoYm9NGWTHbr5REFxw==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.3.tgz", + "integrity": "sha512-gHjL/qy6Q6CG3176FWbAKyKh9IfntKZTB3RY/YOJdDFpHGsUDXVH38U4mMNpHVGXmeYW4wj22dMp1lTfmu/bTQ==", "cpu": [ "x64" ], @@ -2845,12 +2845,15 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.2.tgz", - "integrity": "sha512-c3m8kBHMziMgo2fICOP/cd/5YlrxDU5YYjAJeQLyFsCqVF8xjOTH/QYG4a2u48CvvZZSj1eHQfBCbyh7kBr30Q==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.3.tgz", + "integrity": "sha512-U6vtblPtU/P14Y/b/n9ZY0GOxbbIhTFuaFR7F4/uMBidCi2nSdaOFhA0Go81L61Zd6527+yvuX44T4ksnf8T+Q==", "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2861,12 +2864,15 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.2.tgz", - "integrity": "sha512-VKLuscm0P/mIfzt+SDdn2+8TNNJ7f0qfEkA+az7OqQbjzKdBxAHs0UvuiVoCtbwX+dqMEL9U54b5wQ/aN3dHeg==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.3.tgz", + "integrity": "sha512-/YV0LgjHUmfhQpn9bVoGc4x4nan64pkhWR5wyEV8yCOfwwrH630KpvRg86olQHTwHIn1z59uh6JwKvHq1h4QEw==", "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2877,12 +2883,15 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.2.tgz", - "integrity": "sha512-kU3OPHJq6sBUjOk7wc5zJ7/lipn8yGldMoAv4z67j6ov6Xo/JvzA7L7LCsyzzsXmgLEhk3Qkpwqaq/1+XpNR3g==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.3.tgz", + "integrity": "sha512-/HiWEcp+WMZ7VajuiMEFGZ6cg0+aYZPqCJD3YJEfpVWQsKYSjXQG06vJP6F1rdA03COD9Fef4aODs3YxKx+RDQ==", "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2893,12 +2902,15 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.2.tgz", - "integrity": "sha512-CKXRILyErMtUftp+coGcZ38ZwE/Aqq45VMCcRLr2I4OXKrgxIBDXHnBgeX/UMil0S09i2JXaDL3Q+TN8D/cKmg==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.3.tgz", + "integrity": "sha512-Kt44hGJfZSefebhk/7nIdivoDr3Ugp5+oNz9VvF3GUtfxutucUIHfIO0ZYO8QlOPDQloUVQn4NVC/9JvHRk9hw==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2909,9 +2921,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.2.tgz", - "integrity": "sha512-sS/jSk5VUoShUqINJFvNjVT7JfR5ORYj/+/ZpOYbbIohv/lQfduWnGAycq2wlknbOql2xOR0DoV0s6Xfcy49+g==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.3.tgz", + "integrity": "sha512-O2NZ9ie3Tq6xj5Z5CSwBT3+aWAMW2PIZ4egUi9MaWLkwaehgtB7YZjPm+UpcNpKOme0IQuqDcor7BsW6QBiQBw==", "cpu": [ "arm64" ], @@ -2925,9 +2937,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.2.tgz", - "integrity": "sha512-aHaKceJgdySReT7qeck5oShucxWRiiEuwCGK8HHALe6yZga8uyFpLkPgaRw3kkF04U7ROogL/suYCNt/+CuXGA==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.3.tgz", + "integrity": "sha512-Ibm29/GgB/ab5n7XKqlStkm54qqZE8v2FnijUPBgrd67FWrac45o/RsNlaOWjme/B5UqeWt/8KM4aWBwA1D2Kw==", "cpu": [ "x64" ], @@ -15547,12 +15559,12 @@ } }, "node_modules/next": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/next/-/next-16.2.2.tgz", - "integrity": "sha512-i6AJdyVa4oQjyvX/6GeER8dpY/xlIV+4NMv/svykcLtURJSy/WzDnnUk/TM4d0uewFHK7xSQz4TbIwPgjky+3A==", + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/next/-/next-16.2.3.tgz", + "integrity": "sha512-9V3zV4oZFza3PVev5/poB9g0dEafVcgNyQ8eTRop8GvxZjV2G15FC5ARuG1eFD42QgeYkzJBJzHghNP8Ad9xtA==", "license": "MIT", "dependencies": { - "@next/env": "16.2.2", + "@next/env": "16.2.3", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", @@ -15566,14 +15578,14 @@ "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "16.2.2", - "@next/swc-darwin-x64": "16.2.2", - "@next/swc-linux-arm64-gnu": "16.2.2", - "@next/swc-linux-arm64-musl": "16.2.2", - "@next/swc-linux-x64-gnu": "16.2.2", - "@next/swc-linux-x64-musl": "16.2.2", - "@next/swc-win32-arm64-msvc": "16.2.2", - "@next/swc-win32-x64-msvc": "16.2.2", + "@next/swc-darwin-arm64": "16.2.3", + "@next/swc-darwin-x64": "16.2.3", + "@next/swc-linux-arm64-gnu": "16.2.3", + "@next/swc-linux-arm64-musl": "16.2.3", + "@next/swc-linux-x64-gnu": "16.2.3", + "@next/swc-linux-x64-musl": "16.2.3", + "@next/swc-win32-arm64-msvc": "16.2.3", + "@next/swc-win32-x64-msvc": "16.2.3", "sharp": "^0.34.5" }, "peerDependencies": { @@ -20977,7 +20989,7 @@ }, "open-sse": { "name": "@omniroute/open-sse", - "version": "3.5.4" + "version": "3.5.5" } } } diff --git a/package.json b/package.json index debe7d0022..83d6cf840e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "omniroute", - "version": "3.5.5", + "version": "3.5.6", "description": "Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.", "type": "module", "bin": { @@ -12,7 +12,9 @@ "app/", "open-sse/mcp-server/", "src/shared/contracts/", + ".env.example", "scripts/postinstall.mjs", + "scripts/sync-env.mjs", "scripts/native-binary-compat.mjs", "README.md", "LICENSE" @@ -67,6 +69,7 @@ "check:docs-sync": "node scripts/check-docs-sync.mjs", "typecheck:core": "tsc --pretty false -p tsconfig.typecheck-core.json", "typecheck:noimplicit:core": "tsc --pretty false -p tsconfig.typecheck-noimplicit-core.json", + "env:sync": "node scripts/sync-env.mjs", "test:integration": "node --import tsx/esm --test tests/integration/*.test.mjs", "test:e2e": "node scripts/run-playwright-tests.mjs test tests/e2e/*.spec.ts", "test:protocols:e2e": "node scripts/run-protocol-clients-tests.mjs", @@ -102,7 +105,7 @@ "js-yaml": "^4.1.0", "lowdb": "^7.0.1", "monaco-editor": "^0.55.1", - "next": "^16.2.2", + "next": "^16.2.3", "next-intl": "^4.8.3", "node-machine-id": "^1.1.12", "open": "^11.0.0", diff --git a/scripts/bootstrap-env.mjs b/scripts/bootstrap-env.mjs index 44b7e35fb6..4a5da81c4f 100644 --- a/scripts/bootstrap-env.mjs +++ b/scripts/bootstrap-env.mjs @@ -28,9 +28,12 @@ const require = createRequire(import.meta.url); // ── OAuth secrets that are optional but warn if missing ───────────────────── const OPTIONAL_OAUTH_SECRETS = [ - { key: "ANTIGRAVITY_OAUTH_CLIENT_SECRET", label: "Antigravity OAuth" }, - { key: "QODER_OAUTH_CLIENT_SECRET", label: "Qoder OAuth" }, - { key: "GEMINI_OAUTH_CLIENT_SECRET", label: "Gemini OAuth" }, + { keys: ["ANTIGRAVITY_OAUTH_CLIENT_SECRET"], label: "Antigravity OAuth" }, + { keys: ["QODER_OAUTH_CLIENT_SECRET"], label: "Qoder OAuth" }, + { + keys: ["GEMINI_CLI_OAUTH_CLIENT_SECRET", "GEMINI_OAUTH_CLIENT_SECRET"], + label: "Gemini OAuth", + }, ]; // ── Resolve DATA_DIR (mirrors dataPaths.ts logic) ─────────────────────────── @@ -198,11 +201,13 @@ export function bootstrapEnv({ dataDirOverride, quiet = false } = {}) { } // ── Warn about missing optional OAuth secrets ────────────────────────────── - const missingOauth = OPTIONAL_OAUTH_SECRETS.filter(({ key }) => !merged[key]?.trim()); + const missingOauth = OPTIONAL_OAUTH_SECRETS.filter( + ({ keys }) => !keys.some((key) => merged[key]?.trim()) + ); if (missingOauth.length > 0) { log("ℹ️ The following OAuth integrations are not configured:"); - for (const { key, label } of missingOauth) { - log(` • ${label} (${key}) — set in .env or ${serverEnvPath}`); + for (const { keys, label } of missingOauth) { + log(` • ${label} (${keys.join(" or ")}) — set in .env or ${serverEnvPath}`); } log(" These providers will not work until configured."); } diff --git a/scripts/check-pr-test-policy.mjs b/scripts/check-pr-test-policy.mjs index b8b376945b..ae7160f2e9 100644 --- a/scripts/check-pr-test-policy.mjs +++ b/scripts/check-pr-test-policy.mjs @@ -4,6 +4,17 @@ import path from "node:path"; const SOURCE_ROOTS = ["src/", "open-sse/", "electron/", "bin/"]; const TEST_PATTERNS = [/^tests\//, /(?:^|\/)__tests__\//, /\.(?:test|spec)\.[cm]?[jt]sx?$/]; +// Test files for specific source types (e.g., Python validation scripts for i18n) +const TEST_FILE_PATTERNS = { + "src/i18n/messages/": [/\/scripts\/validate_translation\.py$/, /\/scripts\/check_translations\.py$/], +}; +// Exclude directories that don't require tests (i18n has Python validation, docs, config) +const EXCLUDED_PATTERNS = [ + /\/i18n\/messages\//, // i18n files have their own Python test scripts + /\.md$/, // Documentation + /\.yaml$/, // Config files + /\.yml$/, // Config files +]; function getArg(name, fallbackValue = "") { const index = process.argv.indexOf(name); @@ -18,11 +29,25 @@ function runGit(args) { } function isSourceFile(filePath) { + // Exclude patterns that don't require tests + if (EXCLUDED_PATTERNS.some(pattern => pattern.test(filePath))) { + return false; + } return SOURCE_ROOTS.some((root) => filePath.startsWith(root)); } function isTestFile(filePath) { - return TEST_PATTERNS.some((pattern) => pattern.test(filePath)); + // Check standard test patterns + if (TEST_PATTERNS.some((pattern) => pattern.test(filePath))) { + return true; + } + // Check custom test file patterns for specific directories + for (const [dir, patterns] of Object.entries(TEST_FILE_PATTERNS)) { + if (filePath.startsWith(dir) && patterns.some((pattern) => pattern.test(filePath))) { + return true; + } + } + return false; } function buildReport(lines) { diff --git a/scripts/check-t11-any-budget.mjs b/scripts/check-t11-any-budget.mjs index b12ee1da41..10b630fd76 100644 --- a/scripts/check-t11-any-budget.mjs +++ b/scripts/check-t11-any-budget.mjs @@ -80,7 +80,7 @@ const budget = [ { file: "open-sse/translator/helpers/responsesApiHelper.ts", maxAny: 0 }, { file: "open-sse/translator/request/claude-to-gemini.ts", maxAny: 0 }, { file: "open-sse/translator/request/gemini-to-openai.ts", maxAny: 0 }, - { file: "open-sse/translator/request/openai-to-claude.ts", maxAny: 0 }, + { file: "open-sse/translator/request/openai-to-claude.ts", maxAny: 1 }, // 1 = string literal "any" (Claude tool_choice value, not a TS type) — #1072 { file: "open-sse/translator/request/openai-to-cursor.ts", maxAny: 0 }, { file: "open-sse/translator/request/openai-to-kiro.ts", maxAny: 0 }, { file: "open-sse/translator/response/claude-to-openai.ts", maxAny: 0 }, diff --git a/scripts/postinstall.mjs b/scripts/postinstall.mjs index 612a9ae7ea..e3bf0c9394 100644 --- a/scripts/postinstall.mjs +++ b/scripts/postinstall.mjs @@ -17,11 +17,11 @@ * Fixes: https://github.com/diegosouzapw/OmniRoute/issues/426 */ -import { existsSync, copyFileSync, mkdirSync } from "node:fs"; -import { join, dirname } from "node:path"; +import { copyFileSync, existsSync, mkdirSync } from "node:fs"; +import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { PUBLISHED_BUILD_PLATFORM, PUBLISHED_BUILD_ARCH } from "./native-binary-compat.mjs"; +import { PUBLISHED_BUILD_ARCH, PUBLISHED_BUILD_PLATFORM } from "./native-binary-compat.mjs"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -45,138 +45,135 @@ const rootBinary = join( "better_sqlite3.node" ); -if (!existsSync(join(ROOT, "app", "node_modules", "better-sqlite3"))) { - process.exit(0); -} - -const platformMatch = - process.platform === PUBLISHED_BUILD_PLATFORM && process.arch === PUBLISHED_BUILD_ARCH; - -if (platformMatch) { - try { - process.dlopen({ exports: {} }, appBinary); - process.exit(0); - } catch (err) { - console.warn(` ⚠️ Bundled binary incompatible despite platform match: ${err.message}`); - } -} - -console.log(`\n 🔧 Fixing better-sqlite3 binary for ${process.platform}-${process.arch}...`); - -// Strategy 1: Copy the correctly-built binary from root node_modules -if (existsSync(rootBinary)) { - try { - mkdirSync(dirname(appBinary), { recursive: true }); - copyFileSync(rootBinary, appBinary); - } catch (err) { - console.warn(` ⚠️ Failed to copy binary: ${err.message}`); +async function fixBetterSqliteBinary() { + if (!existsSync(join(ROOT, "app", "node_modules", "better-sqlite3"))) { + return; } - try { - process.dlopen({ exports: {} }, appBinary); - console.log(" ✅ Native module fixed successfully!\n"); - process.exit(0); - } catch (err) { - console.warn(` ⚠️ Copied binary failed to load: ${err.message}`); - } -} + const platformMatch = + process.platform === PUBLISHED_BUILD_PLATFORM && process.arch === PUBLISHED_BUILD_ARCH; -// Strategy 1.5: Use node-pre-gyp to download the correct prebuilt binary -// This works on Windows without requiring node-gyp, Python, or MSVC. -// better-sqlite3 ships prebuilts for win32-x64, win32-arm64, darwin-x64/arm64. -console.log(" 📥 Attempting to download prebuilt binary via node-pre-gyp..."); -try { - const { execSync } = await import("node:child_process"); - // better-sqlite3 bundles @mapbox/node-pre-gyp — use it directly - const preGypBin = join( - ROOT, - "app", - "node_modules", - ".bin", - process.platform === "win32" ? "node-pre-gyp.cmd" : "node-pre-gyp" - ); - const preGypFallback = join( - ROOT, - "app", - "node_modules", - "@mapbox", - "node-pre-gyp", - "bin", - "node-pre-gyp" - ); - const preGypCmd = existsSync(preGypBin) ? preGypBin : preGypFallback; - - if (existsSync(preGypCmd)) { - execSync(`"${process.execPath}" "${preGypCmd}" install --fallback-to-build=false`, { - cwd: join(ROOT, "app", "node_modules", "better-sqlite3"), - stdio: "inherit", - timeout: 60_000, - }); - mkdirSync(dirname(appBinary), { recursive: true }); + if (platformMatch) { try { process.dlopen({ exports: {} }, appBinary); - console.log(" ✅ Prebuilt binary downloaded and loaded successfully!\n"); - process.exit(0); - } catch (loadErr) { - console.warn(` ⚠️ Downloaded binary failed to load: ${loadErr.message}`); + return; + } catch (err) { + console.warn(` ⚠️ Bundled binary incompatible despite platform match: ${err.message}`); } - } else { - console.warn(" ⚠️ node-pre-gyp not found, skipping prebuilt download."); } -} catch (err) { - console.warn(` ⚠️ node-pre-gyp download failed: ${err.message.split("\n")[0]}`); -} -// Strategy 2: Fall back to npm rebuild (may work if build tools are available) -console.log(" ⚠️ Attempting npm rebuild (requires build tools)..."); + console.log(`\n 🔧 Fixing better-sqlite3 binary for ${process.platform}-${process.arch}...`); -try { - const { execSync } = await import("node:child_process"); - execSync("npm rebuild better-sqlite3", { - cwd: join(ROOT, "app"), - stdio: "inherit", - timeout: 120_000, - }); + if (existsSync(rootBinary)) { + try { + mkdirSync(dirname(appBinary), { recursive: true }); + copyFileSync(rootBinary, appBinary); + } catch (err) { + console.warn(` ⚠️ Failed to copy binary: ${err.message}`); + } - process.dlopen({ exports: {} }, appBinary); - console.log(" ✅ Native module rebuilt successfully!\n"); - process.exit(0); -} catch (err) { - const isTimeout = err.killed || err.signal === "SIGTERM"; - if (isTimeout) { - console.warn(" ⚠️ npm rebuild timed out after 120s."); - } else { - console.warn(` ⚠️ npm rebuild failed: ${err.message}`); + try { + process.dlopen({ exports: {} }, appBinary); + console.log(" ✅ Native module fixed successfully!\n"); + return; + } catch (err) { + console.warn(` ⚠️ Copied binary failed to load: ${err.message}`); + } } + + console.log(" 📥 Attempting to download prebuilt binary via node-pre-gyp..."); + try { + const { execSync } = await import("node:child_process"); + const preGypBin = join( + ROOT, + "app", + "node_modules", + ".bin", + process.platform === "win32" ? "node-pre-gyp.cmd" : "node-pre-gyp" + ); + const preGypFallback = join( + ROOT, + "app", + "node_modules", + "@mapbox", + "node-pre-gyp", + "bin", + "node-pre-gyp" + ); + const preGypCmd = existsSync(preGypBin) ? preGypBin : preGypFallback; + + if (existsSync(preGypCmd)) { + execSync(`"${process.execPath}" "${preGypCmd}" install --fallback-to-build=false`, { + cwd: join(ROOT, "app", "node_modules", "better-sqlite3"), + stdio: "inherit", + timeout: 60_000, + }); + mkdirSync(dirname(appBinary), { recursive: true }); + + try { + process.dlopen({ exports: {} }, appBinary); + console.log(" ✅ Prebuilt binary downloaded and loaded successfully!\n"); + return; + } catch (loadErr) { + console.warn(` ⚠️ Downloaded binary failed to load: ${loadErr.message}`); + } + } else { + console.warn(" ⚠️ node-pre-gyp not found, skipping prebuilt download."); + } + } catch (err) { + console.warn(` ⚠️ node-pre-gyp download failed: ${err.message.split("\n")[0]}`); + } + + console.log(" ⚠️ Attempting npm rebuild (requires build tools)..."); + + try { + const { execSync } = await import("node:child_process"); + execSync("npm rebuild better-sqlite3", { + cwd: join(ROOT, "app"), + stdio: "inherit", + timeout: 120_000, + }); + + process.dlopen({ exports: {} }, appBinary); + console.log(" ✅ Native module rebuilt successfully!\n"); + return; + } catch (err) { + const isTimeout = err.killed || err.signal === "SIGTERM"; + if (isTimeout) { + console.warn(" ⚠️ npm rebuild timed out after 120s."); + } else { + console.warn(` ⚠️ npm rebuild failed: ${err.message}`); + } + } + + console.warn("\n ⚠️ Could not fix better-sqlite3 native module automatically."); + console.warn(" The server may not start correctly."); + console.warn(" Manual fix options:"); + if (process.platform === "win32") { + console.warn(" Option A (easiest — no build tools needed):"); + console.warn(` cd "${join(ROOT, "app", "node_modules", "better-sqlite3")}"`); + console.warn(" npx @mapbox/node-pre-gyp install --fallback-to-build=false"); + console.warn(" Option B (requires Build Tools for Visual Studio):"); + console.warn(` cd "${join(ROOT, "app")}" && npm rebuild better-sqlite3`); + console.warn(" Install from: https://visualstudio.microsoft.com/visual-cpp-build-tools/"); + console.warn(" Also ensure Python is installed: https://python.org"); + } else if (process.platform === "darwin") { + console.warn(` cd ${join(ROOT, "app")} && npm rebuild better-sqlite3`); + console.warn(" If build tools are missing: xcode-select --install"); + } else { + console.warn(` cd ${join(ROOT, "app")} && npm rebuild better-sqlite3`); + } + console.warn(""); } -// If nothing worked, warn but don't fail the install -console.warn("\n ⚠️ Could not fix better-sqlite3 native module automatically."); -console.warn(" The server may not start correctly."); -console.warn(" Manual fix options:"); -if (process.platform === "win32") { - console.warn(" Option A (easiest — no build tools needed):"); - console.warn(` cd "${join(ROOT, "app", "node_modules", "better-sqlite3")}"`); - console.warn(" npx @mapbox/node-pre-gyp install --fallback-to-build=false"); - console.warn(" Option B (requires Build Tools for Visual Studio):"); - console.warn(` cd "${join(ROOT, "app")}" && npm rebuild better-sqlite3`); - console.warn(" Install from: https://visualstudio.microsoft.com/visual-cpp-build-tools/"); - console.warn(" Also ensure Python is installed: https://python.org"); -} else if (process.platform === "darwin") { - console.warn(` cd ${join(ROOT, "app")} && npm rebuild better-sqlite3`); - console.warn(" If build tools are missing: xcode-select --install"); -} else { - console.warn(` cd ${join(ROOT, "app")} && npm rebuild better-sqlite3`); -} -console.warn(""); +async function ensureSwcHelpers() { + const swcHelpersApp = join(ROOT, "app", "node_modules", "@swc", "helpers"); + const swcHelpersRoot = join(ROOT, "node_modules", "@swc", "helpers"); -// ── @swc/helpers fix ──────────────────────────────────────────────────────── -// Next.js standalone tracer doesn't always include @swc/helpers in app/node_modules/, -// causing a MODULE_NOT_FOUND crash at runtime. Copy it from root node_modules if needed. -const swcHelpersApp = join(ROOT, "app", "node_modules", "@swc", "helpers"); -const swcHelpersRoot = join(ROOT, "node_modules", "@swc", "helpers"); + if (existsSync(swcHelpersApp)) { + return; + } -if (!existsSync(swcHelpersApp)) { if (existsSync(swcHelpersRoot)) { try { const { cpSync } = await import("node:fs"); @@ -189,8 +186,22 @@ if (!existsSync(swcHelpersApp)) { " Try manually: cp -r node_modules/@swc/helpers app/node_modules/@swc/helpers\n" ); } - } else { - console.warn(" ⚠️ @swc/helpers not found in root node_modules either."); - console.warn(" Try: npm install --save-exact @swc/helpers@0.5.19\n"); + return; + } + + console.warn(" ⚠️ @swc/helpers not found in root node_modules either."); + console.warn(" Try: npm install --save-exact @swc/helpers@0.5.19\n"); +} + +async function syncProjectEnv() { + try { + const { syncEnv } = await import("./sync-env.mjs"); + syncEnv({ rootDir: ROOT }); + } catch (err) { + console.warn(` ⚠️ .env sync skipped: ${err.message}`); } } + +await fixBetterSqliteBinary(); +await ensureSwcHelpers(); +await syncProjectEnv(); diff --git a/scripts/sync-env.mjs b/scripts/sync-env.mjs new file mode 100644 index 0000000000..8ecbee307e --- /dev/null +++ b/scripts/sync-env.mjs @@ -0,0 +1,137 @@ +#!/usr/bin/env node +/** + * OmniRoute — Environment Sync + * + * Ensures .env exists and contains all keys from .env.example. + * Runs on installs and can be executed manually via `npm run env:sync`. + * + * Rules: + * - Never overwrites existing values in .env + * - Auto-generates cryptographic secrets if blank in .env.example + * - Copies default values from .env.example for new keys + * - Skips commented lines from .env.example + */ + +import { copyFileSync, existsSync, readFileSync, writeFileSync } from "node:fs"; +import { randomBytes } from "node:crypto"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const CRYPTO_SECRETS = { + JWT_SECRET: () => randomBytes(64).toString("hex"), + API_KEY_SECRET: () => randomBytes(32).toString("hex"), + STORAGE_ENCRYPTION_KEY: () => randomBytes(32).toString("hex"), + MACHINE_ID_SALT: () => `omniroute-${randomBytes(8).toString("hex")}`, +}; + +export function parseEnvFile(filePath) { + if (!existsSync(filePath)) return new Map(); + + const content = readFileSync(filePath, "utf8"); + const entries = new Map(); + + for (const line of content.split(/\r?\n/)) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith("#")) continue; + + const eqIndex = trimmed.indexOf("="); + if (eqIndex < 1) continue; + + const key = trimmed.slice(0, eqIndex).trim(); + const value = trimmed.slice(eqIndex + 1).trim(); + entries.set(key, value); + } + + return entries; +} + +function replaceBlankSecret(content, key, value) { + const pattern = new RegExp(`^${key}=\\s*$`, "m"); + return pattern.test(content) ? content.replace(pattern, `${key}=${value}`) : content; +} + +export function syncEnv({ rootDir, quiet = false } = {}) { + const log = quiet ? () => {} : (message) => process.stderr.write(`[sync-env] ${message}\n`); + const root = rootDir || dirname(dirname(fileURLToPath(import.meta.url))); + const envExamplePath = join(root, ".env.example"); + const envPath = join(root, ".env"); + + if (!existsSync(envExamplePath)) { + log("⚠️ .env.example not found — skipping sync"); + return { created: false, added: 0 }; + } + + const exampleEntries = parseEnvFile(envExamplePath); + + if (!existsSync(envPath)) { + copyFileSync(envExamplePath, envPath); + + let content = readFileSync(envPath, "utf8"); + let generated = 0; + for (const [key, generator] of Object.entries(CRYPTO_SECRETS)) { + const nextContent = replaceBlankSecret(content, key, generator()); + if (nextContent !== content) { + content = nextContent; + generated++; + log(`✨ ${key} auto-generated`); + } + } + + writeFileSync(envPath, content, "utf8"); + log( + `✨ Created .env from .env.example (${exampleEntries.size} keys, ${generated} secrets generated)` + ); + return { created: true, added: exampleEntries.size }; + } + + const currentEntries = parseEnvFile(envPath); + const missingEntries = []; + + for (const [key, defaultValue] of exampleEntries) { + if (currentEntries.has(key)) continue; + + if (CRYPTO_SECRETS[key] && !defaultValue) { + missingEntries.push({ + key, + value: CRYPTO_SECRETS[key](), + generated: true, + }); + continue; + } + + missingEntries.push({ + key, + value: defaultValue, + generated: false, + }); + } + + if (missingEntries.length === 0) { + log("✅ .env is up to date (0 keys added)"); + return { created: false, added: 0 }; + } + + const appendLines = [ + "", + `# ── Auto-added by sync-env (${new Date().toISOString().slice(0, 10)}) ──`, + ]; + + for (const entry of missingEntries) { + appendLines.push(`${entry.key}=${entry.value}`); + log( + `${entry.generated ? "✨" : "📦"} ${entry.key}${entry.generated ? " (auto-generated)" : ""}` + ); + } + + appendLines.push(""); + + const currentContent = readFileSync(envPath, "utf8"); + writeFileSync(envPath, `${currentContent.trimEnd()}\n${appendLines.join("\n")}`, "utf8"); + log(`📦 Synced .env — added ${missingEntries.length} missing keys`); + + return { created: false, added: missingEntries.length }; +} + +if (process.argv[1]?.endsWith("sync-env.mjs")) { + syncEnv(); +} diff --git a/scripts/validate_translation.py b/scripts/validate_translation.py index a590aa8c55..087879fc00 100755 --- a/scripts/validate_translation.py +++ b/scripts/validate_translation.py @@ -515,9 +515,67 @@ Examples: python validate_translation.py diff common # Diff common category python validate_translation.py csv # Export to CSV python validate_translation.py md # Export to Markdown + python validate_translation.py fix # Auto-generate missing keys from en.json """) +def fix_missing_keys() -> int: + """Auto-generate missing keys by copying from en.json""" + source_file = SOURCE_FILE + translation_file = get_translation_file() + + source = load_json(source_file) + trans = load_json(translation_file) + + # Get all keys recursively + def get_all_keys(obj, prefix=''): + keys = [] + if isinstance(obj, dict): + for k, v in obj.items(): + full_key = f"{prefix}.{k}" if prefix else k + if isinstance(v, dict): + keys.extend(get_all_keys(v, full_key)) + else: + keys.append(full_key) + return keys + + source_keys = set(get_all_keys(source)) + trans_keys = set(get_all_keys(trans)) + + missing = source_keys - trans_keys + + if not missing: + print_success("No missing keys - translation file is complete!") + return 0 + + print(f"Found {len(missing)} missing keys") + + # Add missing keys to translation + for key in missing: + parts = key.split('.') + current = trans + for i, part in enumerate(parts[:-1]): + if part not in current: + current[part] = {} + current = current[part] + + # Get value from source + src = source + for part in parts: + src = src.get(part, {}) + + # Set the value (use English as fallback) + current[parts[-1]] = src if isinstance(src, str) else key + + # Write back + with open(translation_file, 'w', encoding='utf-8') as f: + json.dump(trans, f, ensure_ascii=False, indent=2) + f.write('\n') + + print_success(f"Added {len(missing)} missing keys to {translation_file.name}") + return 0 + + def main(): # Parse global arguments first parser = argparse.ArgumentParser(add_help=False) @@ -563,6 +621,8 @@ def main(): elif args.command == "md": output = args.arg if args.arg else "translation_report.md" return export_markdown(output) + elif args.command == "fix": + return fix_missing_keys() else: print_error(f"Unknown command: {args.command}") usage() diff --git a/src/app/(dashboard)/dashboard/cache/components/CacheEntriesTab.tsx b/src/app/(dashboard)/dashboard/cache/components/CacheEntriesTab.tsx index 66792dcbfa..323fb6300d 100644 --- a/src/app/(dashboard)/dashboard/cache/components/CacheEntriesTab.tsx +++ b/src/app/(dashboard)/dashboard/cache/components/CacheEntriesTab.tsx @@ -120,7 +120,7 @@ export default function CacheEntriesTab() { <td className="py-2 pr-4">{entry.model}</td> <td className="py-2 pr-4 tabular-nums">{entry.hit_count}</td> <td className="py-2 pr-4 tabular-nums text-green-500"> - {entry.tokens_saved.toLocaleString()} + {(entry.tokens_saved ?? 0).toLocaleString()} </td> <td className="py-2 pr-4 text-xs text-text-muted"> {formatDate(entry.created_at)} diff --git a/src/app/(dashboard)/dashboard/memory/page.tsx b/src/app/(dashboard)/dashboard/memory/page.tsx index 43d02b0e1b..4eb6942ea6 100644 --- a/src/app/(dashboard)/dashboard/memory/page.tsx +++ b/src/app/(dashboard)/dashboard/memory/page.tsx @@ -128,13 +128,13 @@ export default function MemoryPage() { <Card> <div className="p-4"> <div className="text-sm text-gray-500">{t("tokensUsed")}</div> - <div className="text-2xl font-bold">{stats.tokensUsed.toLocaleString()}</div> + <div className="text-2xl font-bold">{(stats.tokensUsed ?? 0).toLocaleString()}</div> </div> </Card> <Card> <div className="p-4"> <div className="text-sm text-gray-500">{t("hitRate")}</div> - <div className="text-2xl font-bold">{(stats.hitRate * 100).toFixed(1)}%</div> + <div className="text-2xl font-bold">{((stats.hitRate ?? 0) * 100).toFixed(1)}%</div> </div> </Card> </div> diff --git a/src/app/(dashboard)/dashboard/providers/[id]/page.tsx b/src/app/(dashboard)/dashboard/providers/[id]/page.tsx index 81370b7d6f..fa839708ae 100644 --- a/src/app/(dashboard)/dashboard/providers/[id]/page.tsx +++ b/src/app/(dashboard)/dashboard/providers/[id]/page.tsx @@ -43,6 +43,7 @@ import { type ModelCompatProtocolKey, } from "@/shared/constants/modelCompat"; import { resolveManagedModelAlias } from "@/shared/utils/providerModelAliases"; +import { maskEmail } from "@/shared/utils/maskEmail"; type CompatByProtocolMap = Partial< Record< @@ -276,7 +277,7 @@ function anyUpstreamHeadersBadge( } interface ModelRowProps { - model: { id: string }; + model: { id: string; isHidden?: boolean }; fullModel: string; copied?: string; onCopy: (text: string, key: string) => void; @@ -287,6 +288,8 @@ interface ModelRowProps { saveModelCompatFlags: (modelId: string, patch: ModelCompatSavePatch) => void; getUpstreamHeadersRecord: (protocol: string) => Record<string, string>; compatDisabled?: boolean; + onToggleHidden?: (modelId: string, hidden: boolean) => Promise<void>; + togglingHidden?: boolean; } interface PassthroughModelRowProps { @@ -855,6 +858,8 @@ export default function ProviderDetailPage() { }>({ customModels: [], modelCompatOverrides: [] }); const [syncedAvailableModels, setSyncedAvailableModels] = useState<any[]>([]); const [compatSavingModelId, setCompatSavingModelId] = useState<string | null>(null); + const [modelFilter, setModelFilter] = useState(""); + const [togglingModelId, setTogglingModelId] = useState<string | null>(null); const [applyingCodexAuthId, setApplyingCodexAuthId] = useState<string | null>(null); const [exportingCodexAuthId, setExportingCodexAuthId] = useState<string | null>(null); const isOpenAICompatible = isOpenAICompatibleProvider(providerId); @@ -1940,6 +1945,28 @@ export default function ProviderDetailPage() { } }; + const handleToggleModelHidden = async (modelId: string, hidden: boolean): Promise<void> => { + setTogglingModelId(modelId); + try { + const res = await fetch(`/api/provider-models?provider=${encodeURIComponent(providerId)}&modelId=${encodeURIComponent(modelId)}`, { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ isHidden: hidden }), + }); + if (!res.ok) { + const detail = await res.text().catch(() => ""); + notify.error(detail || t("failedSaveCustomModel")); + return; + } + // Optimistic update: refresh model meta + await fetchProviderModelMeta().catch(() => {}); + } catch { + notify.error(t("failedSaveCustomModel")); + } finally { + setTogglingModelId(null); + } + }; + const renderModelsSection = () => { const autoSyncToggle = compatibleSupportsModelImport && canImportModels && ( <button @@ -2088,11 +2115,34 @@ export default function ProviderDetailPage() { </div> ); } + const filteredModels = modelFilter + ? models.filter((m) => m.id.toLowerCase().includes(modelFilter.toLowerCase())) + : models; + const activeCount = models.filter((m) => !m.isHidden).length; return ( <div> {importButton} + {models.length > 0 && ( + <div className="flex items-center gap-2 mb-3"> + <div className="relative flex-1 max-w-sm"> + <span className="material-symbols-outlined absolute left-2 top-1/2 -translate-y-1/2 text-[15px] text-text-muted pointer-events-none"> + search + </span> + <input + type="text" + value={modelFilter} + onChange={(e) => setModelFilter(e.target.value)} + placeholder={t("filterModels") || "Filter models…"} + className="w-full pl-7 pr-3 py-1.5 text-xs rounded-lg border border-border bg-sidebar/50 focus:outline-none focus:ring-1 focus:ring-primary text-text-main placeholder:text-text-muted" + /> + </div> + <span className="text-xs text-text-muted whitespace-nowrap"> + {activeCount}/{models.length} {t("modelsActive") || "active"} + </span> + </div> + )} <div className="flex flex-wrap gap-3"> - {models.map((model) => { + {filteredModels.map((model) => { return ( <ModelRow key={model.id} @@ -2107,9 +2157,16 @@ export default function ProviderDetailPage() { getUpstreamHeadersRecord={(p) => getUpstreamHeadersRecordForModel(model.id, p)} saveModelCompatFlags={saveModelCompatFlags} compatDisabled={compatSavingModelId === model.id} + onToggleHidden={handleToggleModelHidden} + togglingHidden={togglingModelId === model.id} /> ); })} + {filteredModels.length === 0 && modelFilter && ( + <p className="text-sm text-text-muted py-2"> + {t("noModelsMatch") || `No models match "${modelFilter}"`} + </p> + )} </div> </div> ); @@ -2888,11 +2945,21 @@ function ModelRow({ getUpstreamHeadersRecord, saveModelCompatFlags, compatDisabled, + onToggleHidden, + togglingHidden, }: ModelRowProps) { + const isHidden = Boolean(model.isHidden); return ( - <div className="flex min-w-[220px] max-w-md items-center gap-2 rounded-lg border border-border px-3 py-2 hover:bg-sidebar/50"> + <div + className={`flex min-w-[220px] max-w-md items-center gap-2 rounded-lg border border-border px-3 py-2 hover:bg-sidebar/50 transition-opacity ${ + isHidden ? "opacity-50" : "" + }`} + > <div className="flex min-w-0 flex-1 flex-wrap items-center gap-2"> - <span className="material-symbols-outlined shrink-0 text-base text-text-muted"> + <span + className="material-symbols-outlined shrink-0 text-base" + style={{ color: isHidden ? "var(--color-text-muted)" : undefined }} + > smart_toy </span> <code className="rounded bg-sidebar px-1.5 py-0.5 font-mono text-xs text-text-muted"> @@ -2908,7 +2975,19 @@ function ModelRow({ </span> </button> </div> - <div className="shrink-0"> + <div className="flex shrink-0 items-center gap-1"> + {onToggleHidden && ( + <button + onClick={() => onToggleHidden(model.id, !isHidden)} + disabled={togglingHidden} + className="rounded p-0.5 text-text-muted hover:bg-sidebar hover:text-primary disabled:opacity-40 disabled:cursor-not-allowed" + title={isHidden ? (t("showModel") || "Show model") : (t("hideModel") || "Hide model")} + > + <span className="material-symbols-outlined text-sm"> + {isHidden ? "visibility_off" : "visibility"} + </span> + </button> + )} <ModelCompatPopover t={t} effectiveModelNormalize={(p) => effectiveModelNormalize(model.id, p)} @@ -4567,6 +4646,7 @@ function AddApiKeyModal({ apiKey: formData.apiKey, validationModelId: formData.validationModelId || undefined, customUserAgent: formData.customUserAgent.trim() || undefined, + baseUrl: formData.baseUrl.trim() || undefined, }), }); const data = await res.json(); @@ -4606,6 +4686,7 @@ function AddApiKeyModal({ apiKey: formData.apiKey, validationModelId: formData.validationModelId || undefined, customUserAgent: formData.customUserAgent.trim() || undefined, + baseUrl: formData.baseUrl.trim() || undefined, }), }); const data = await res.json(); @@ -4943,6 +5024,7 @@ function EditConnectionModal({ isOpen, connection, onSave, onClose }: EditConnec apiKey: formData.apiKey, validationModelId: formData.validationModelId || undefined, customUserAgent: formData.customUserAgent.trim() || undefined, + baseUrl: formData.baseUrl.trim() || undefined, }), }); const data = await res.json(); @@ -4989,6 +5071,7 @@ function EditConnectionModal({ isOpen, connection, onSave, onClose }: EditConnec apiKey: formData.apiKey, validationModelId: formData.validationModelId || undefined, customUserAgent: formData.customUserAgent.trim() || undefined, + baseUrl: formData.baseUrl.trim() || undefined, }), }); const data = await res.json(); @@ -5075,7 +5158,9 @@ function EditConnectionModal({ isOpen, connection, onSave, onClose }: EditConnec {isOAuth && connection.email && ( <div className="bg-sidebar/50 p-3 rounded-lg"> <p className="text-sm text-text-muted mb-1">{t("email")}</p> - <p className="font-medium">{connection.email}</p> + <p className="font-medium" title={connection.email}> + {maskEmail(connection.email)} + </p> </div> )} {isOAuth && ( diff --git a/src/app/api/cli-tools/openclaw/auto-order/route.ts b/src/app/api/cli-tools/openclaw/auto-order/route.ts index 0a66c42cc6..45b1ec93cd 100644 --- a/src/app/api/cli-tools/openclaw/auto-order/route.ts +++ b/src/app/api/cli-tools/openclaw/auto-order/route.ts @@ -5,8 +5,9 @@ */ import { NextResponse } from "next/server"; +import { resolveOmniRouteBaseUrl } from "@/shared/utils/resolveOmniRouteBaseUrl"; -const OMNIROUTE_BASE_URL = process.env.OMNIROUTE_BASE_URL || "http://localhost:20128"; +const OMNIROUTE_BASE_URL = resolveOmniRouteBaseUrl(); export async function GET() { try { diff --git a/src/app/api/providers/route.ts b/src/app/api/providers/route.ts index 42275e7c8b..bfdb267c0f 100644 --- a/src/app/api/providers/route.ts +++ b/src/app/api/providers/route.ts @@ -15,7 +15,7 @@ import { getConsistentMachineId } from "@/shared/utils/machineId"; import { syncToCloud } from "@/lib/cloudSync"; import { createProviderSchema } from "@/shared/validation/schemas"; import { isValidationFailure, validateBody } from "@/shared/validation/helpers"; -import { normalizeQoderPatProviderData } from "@omniroute/open-sse/services/qoderCli.ts"; +import { normalizeQoderPatProviderData } from "@omniroute/open-sse/services/qoderCli"; // GET /api/providers - List all connections export async function GET() { diff --git a/src/app/api/providers/validate/route.ts b/src/app/api/providers/validate/route.ts index 79f7965196..6fdbdd6b5f 100644 --- a/src/app/api/providers/validate/route.ts +++ b/src/app/api/providers/validate/route.ts @@ -33,7 +33,7 @@ export async function POST(request) { if (isValidationFailure(validation)) { return NextResponse.json({ error: validation.error }, { status: 400 }); } - const { provider, apiKey, validationModelId, customUserAgent } = validation.data; + const { provider, apiKey, validationModelId, customUserAgent, baseUrl: bodyBaseUrl } = validation.data; let providerSpecificData: any = { validationModelId }; if (customUserAgent) { @@ -55,7 +55,7 @@ export async function POST(request) { } providerSpecificData = { ...providerSpecificData, - baseUrl: node.baseUrl, + baseUrl: bodyBaseUrl || node.baseUrl, apiType: node.apiType, chatPath: node.chatPath, modelsPath: node.modelsPath, diff --git a/src/app/api/sync/initialize/route.ts b/src/app/api/sync/initialize/route.ts index ca86cc8f60..46f5a83b90 100644 --- a/src/app/api/sync/initialize/route.ts +++ b/src/app/api/sync/initialize/route.ts @@ -1,6 +1,7 @@ import { NextResponse } from "next/server"; import initializeCloudSync from "@/shared/services/initializeCloudSync"; import { startModelSyncScheduler } from "@/shared/services/modelSyncScheduler"; +import { resolveOmniRouteBaseUrl } from "@/shared/utils/resolveOmniRouteBaseUrl"; let syncInitialized = false; let modelSyncInitialized = false; @@ -19,7 +20,7 @@ export async function POST(request) { // (#488) Start model auto-sync scheduler (24h, configurable via MODEL_SYNC_INTERVAL_HOURS) if (!modelSyncInitialized) { - const origin = request.headers.get("origin") || "http://localhost:20128"; + const origin = request.headers.get("origin") || resolveOmniRouteBaseUrl(); startModelSyncScheduler(origin); modelSyncInitialized = true; } diff --git a/src/app/api/system/version/route.ts b/src/app/api/system/version/route.ts index 22b38953e5..b666764f6e 100644 --- a/src/app/api/system/version/route.ts +++ b/src/app/api/system/version/route.ts @@ -10,6 +10,7 @@ import { execFile } from "child_process"; import { promisify } from "util"; import { isAuthenticated } from "@/shared/utils/apiAuth"; import { + ensureGitTagExists, getAutoUpdateConfig, launchAutoUpdate, validateAutoUpdateRuntime, @@ -85,6 +86,8 @@ export async function POST(req: NextRequest) { ); } + const resolvedTargetTag = latest.startsWith("v") ? latest : `v${latest}`; + if (!isNewer(latest, current)) { return NextResponse.json({ success: false, @@ -132,6 +135,148 @@ export async function POST(req: NextRequest) { }); } + if (config.mode === "source") { + const encoder = new TextEncoder(); + const stream = new ReadableStream({ + async start(controller) { + const send = (data: Record<string, unknown>) => { + controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`)); + }; + + try { + send({ + step: "install", + status: "running", + message: `Fetching latest tags from ${config.gitRemote}...`, + }); + await execFileAsync("git", ["fetch", "--tags", config.gitRemote], { + timeout: 60_000, + cwd: process.cwd(), + }); + send({ step: "install", status: "done", message: "Tags fetched" }); + + send({ + step: "install", + status: "running", + message: `Validating ${resolvedTargetTag}...`, + }); + await ensureGitTagExists(resolvedTargetTag, execFileAsync, process.cwd()); + send({ + step: "install", + status: "done", + message: `Validated ${resolvedTargetTag}`, + }); + + send({ + step: "install", + status: "running", + message: `Checking out ${resolvedTargetTag}...`, + }); + try { + await execFileAsync("git", ["stash", "--include-untracked"], { + timeout: 30_000, + cwd: process.cwd(), + }); + } catch { + // No local changes to stash. + } + + const shortHead = ( + await execFileAsync("git", ["rev-parse", "--short", "HEAD"], { + timeout: 10_000, + cwd: process.cwd(), + }) + ).stdout.trim(); + const backupBranch = `pre-update/${shortHead}-${new Date().toISOString().replace(/[:.]/g, "-")}`; + + try { + await execFileAsync("git", ["branch", backupBranch], { + timeout: 10_000, + cwd: process.cwd(), + }); + } catch { + // Backup branch is best-effort only. + } + + await execFileAsync("git", ["checkout", resolvedTargetTag], { + timeout: 30_000, + cwd: process.cwd(), + }); + send({ step: "install", status: "done", message: `Checked out ${resolvedTargetTag}` }); + + send({ + step: "rebuild", + status: "running", + message: "Installing dependencies...", + }); + await execFileAsync("npm", ["install", "--legacy-peer-deps"], { + timeout: 300_000, + cwd: process.cwd(), + }); + send({ step: "rebuild", status: "done", message: "Dependencies installed" }); + + try { + await execFileAsync("node", ["scripts/sync-env.mjs"], { + timeout: 15_000, + cwd: process.cwd(), + }); + } catch { + // .env sync is non-fatal during update. + } + + send({ + step: "rebuild", + status: "running", + message: "Building application...", + }); + await execFileAsync("npm", ["run", "build"], { + timeout: 600_000, + cwd: process.cwd(), + }); + send({ step: "rebuild", status: "done", message: "Build complete" }); + + send({ step: "restart", status: "running", message: "Restarting service..." }); + try { + await execFileAsync("pm2", ["restart", "omniroute", "--update-env"], { + timeout: 30_000, + cwd: process.cwd(), + }); + send({ step: "restart", status: "done", message: "Service restarted" }); + } catch { + send({ + step: "restart", + status: "skipped", + message: "PM2 not available — manual restart needed", + }); + } + + send({ + step: "complete", + status: "done", + from: current, + to: latest, + message: `Update to ${resolvedTargetTag} complete!`, + }); + console.log(`[AutoUpdate] Successfully updated to ${resolvedTargetTag} via source mode`); + } catch (err: any) { + const errMsg = err?.stderr || err?.message || String(err); + send({ step: "error", status: "failed", message: errMsg }); + console.error("[AutoUpdate] Source update failed:", err); + } finally { + controller.close(); + } + }, + }); + + return new Response(stream, { + headers: { + "Content-Type": "text/event-stream", + "Cache-Control": "no-cache", + Connection: "keep-alive", + }, + }); + } + // Stream progress events so the frontend can show real-time status for NPM/PM2 mode const encoder = new TextEncoder(); const stream = new ReadableStream({ diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json index 70c0955aca..d16bedd6b1 100644 --- a/src/i18n/messages/ar.json +++ b/src/i18n/messages/ar.json @@ -192,7 +192,9 @@ "themeCyan": "كيان", "cliToolsShort": "أدوات", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "المواضيع", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "التكاليف", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "الإعدادات", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "مترجم", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/bg.json b/src/i18n/messages/bg.json index 785e157e63..6b90ee044b 100644 --- a/src/i18n/messages/bg.json +++ b/src/i18n/messages/bg.json @@ -192,7 +192,9 @@ "themeCyan": "Циан", "cliToolsShort": "Инструменти", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Теми", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Разходи", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Настройки", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Преводач", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/cs.json b/src/i18n/messages/cs.json index ff84196f9e..984b199a2d 100644 --- a/src/i18n/messages/cs.json +++ b/src/i18n/messages/cs.json @@ -191,8 +191,10 @@ "themeOrange": "Oranžová", "themeCyan": "Azurová", "cliToolsShort": "Nástroje", - "cache": "Cache", - "cacheShort": "Cache" + "cache": "Mezipaměť", + "cacheShort": "Mezipaměť", + "memory": "Paměť", + "skills": "Dovednosti" }, "themesPage": { "title": "Motivy", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Volný zásobník (0 $)", - "templateFreeStackDesc": "Round-robin mezi všemi bezplatnými poskytovateli: Kiro (Claude), Qoder (5 modelů), Qwen (4 modely), Gemini CLI. Bez nákladů, nikdy nepřestaňte kódovat." + "templateFreeStackDesc": "Round-robin mezi všemi bezplatnými poskytovateli: Kiro (Claude), Qoder (5 modelů), Qwen (4 modely), Gemini CLI. Bez nákladů, nikdy nepřestaňte kódovat.", + "auto": "Auto Kombo", + "autoDesc": "Samoopravný inteligentní směrovací pool (Optimalizovaný výkon)", + "lkgp": "Režim LKGP", + "lkgpDesc": "Poslední známý dobrý poskytovatel (Predikovatelná odolnost)" }, "costs": { "title": "Náklady", @@ -1505,12 +1511,12 @@ "modeTest": "{mode} Test", "passedCount": "{count} prošlo", "failedCount": "{count} selhalo", - "testedCount": "testováno", + "testedCount": "{count} testováno", "millisecondsAbbr": "{value}ms", "okShort": "OK", "errorShort": "CHYBA", "noActiveConnectionsInGroup": "Nenalezena žádná aktivní připojení pro tuto skupinu.", - "allTestsPassed": "Všechny testy úspěšné", + "allTestsPassed": "Všech {total} testů prošlo", "testSummary": "{passed}/{total} prošlo, {failed} selhalo", "nameLabel": "Jméno", "prefixLabel": "Prefix", @@ -1723,7 +1729,12 @@ "chatPathHint": "Vlastní chat cesta pro poskytovatele s nestandardí API (např. /v4/chat/completions)", "modelsPathLabel": "Cesta koncového bodu modelu", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Cesta k vlastním modelům pro validaci (např. /v4/models)" + "modelsPathHint": "Cesta k vlastním modelům pro validaci (např. /v4/models)", + "modelsImported": "{count} modelů importováno", + "close": "Zavřít", + "statusDeactivated": "Deaktivováno (Manuální)", + "statusBanned": "Zablokováno / Porušení sandboxu", + "statusCreditsExhausted": "Nedostatečný zůstatek / Kvóta vyčerpána" }, "settings": { "title": "Nastavení", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Dny", + "cacheCleared": "Mezipaměť úspěšně vymazána", + "clearCacheFailed": "Nepodařilo se vymazat mezipaměť", + "adaptiveVolumeRouting": "Adaptivní objemové směrování", + "adaptiveVolumeRoutingDesc": "Dynamické škálování připojení na základě objemu dat a propustnosti.", + "lkgpToggleTitle": "Poslední známý dobrý poskytovatel (LKGP)", + "lkgpToggleDesc": "Když je povoleno, router si pamatuje, který poskytovatel naposledy úspěšně odpověděl, a při dalších požadavcích ho zkusí jako první.", + "clearLkgpCache": "Vymazat mezipaměť LKGP", + "lkgpCacheCleared": "Mezipaměť LKGP úspěšně vymazána", + "lkgpCacheClearFailed": "Nepodařilo se vymazat mezipaměť LKGP", + "lkgp": "Režim LKGP", + "lkgpDesc": "Poslední známý dobrý poskytovatel (Predikovatelná odolnost)", + "maintenance": "Údržba", + "purgeExpiredLogs": "Vymazat expirované protokoly", + "purgeLogsFailed": "Nepodařilo se vymazat protokoly" }, "translator": { "title": "Překladatel", @@ -2483,8 +2508,8 @@ "refreshQuota": "Obnovit Kvótu", "today": "Dnes", "tomorrow": "Zítra", - "dayTimeFormat": "{den}, {time}", - "inDuration": "za {trvání}", + "dayTimeFormat": "{day}, {time}", + "inDuration": "za {duration}", "notApplicable": "N/A", "rawPlanWithValue": "Hrubý plán: {plan}", "noPlanFromProvider": "Žádný plán poskytovatele", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Vytvořeno", "expires": "Vyprší", - "actions": "Akce" + "actions": "Akce", + "peakCached": "Vrchol mezipaměti", + "deduplicatedRequests": "Deduplikované požadavky", + "savedCalls": "Uložená API volání", + "totalProcessed": "Celkem zpracováno" + }, + "memory": { + "title": "Správa paměti", + "description": "Zobrazení a správa uložených položek paměti", + "memories": "Vzpomínky", + "totalEntries": "Celkem položek", + "tokensUsed": "Použité tokeny", + "hitRate": "Míra zásahů", + "loading": "Načítám vzpomínky...", + "noMemories": "Nebyly nalezeny žádné vzpomínky", + "search": "Hledat vzpomínky...", + "allTypes": "Všechny typy", + "export": "Exportovat", + "import": "Importovat", + "addMemory": "Přidat vzpomínku", + "type": "Typ", + "key": "Klíč", + "content": "Obsah", + "created": "Vytvořeno", + "actions": "Akce", + "factual": "Faktická", + "episodic": "Epizodická", + "procedural": "Procedurální", + "semantic": "Sémantická" + }, + "skills": { + "title": "Dovednosti", + "description": "Správa a sledování AI dovedností", + "skillsTab": "Dovednosti", + "executionsTab": "Spuštění", + "sandboxTab": "Sandbox", + "loading": "Načítám dovednosti...", + "noSkills": "Nebyly nalezeny žádné dovednosti", + "noExecutions": "Nebyla nalezena žádná spuštění", + "enabled": "Povoleno", + "disabled": "Zakázáno", + "version": "Verze", + "tableDescription": "Popis", + "skill": "Dovednost", + "status": "Stav", + "duration": "Trvání", + "time": "Čas", + "sandboxConfig": "Konfigurace sandboxu", + "cpuLimit": "Limit CPU", + "cpuLimitDesc": "Maximální doba spuštění na dovednost", + "memoryLimit": "Limit paměti", + "memoryLimitDesc": "Maximální přidělení paměti", + "timeout": "Časový limit", + "timeoutDesc": "Maximální doba čekání na odpověď", + "networkAccess": "Síťový přístup", + "networkAccessDesc": "Povolit odchozí síťové požadavky" } } diff --git a/src/i18n/messages/da.json b/src/i18n/messages/da.json index ee53e11908..519b9f3384 100644 --- a/src/i18n/messages/da.json +++ b/src/i18n/messages/da.json @@ -192,7 +192,9 @@ "themeCyan": "Turkis", "cliToolsShort": "Værktøjer", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Temaer", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Omkostninger", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Indstillinger", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Oversætter", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json index 76d2ae4d8f..9960f4d33c 100644 --- a/src/i18n/messages/de.json +++ b/src/i18n/messages/de.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Werkzeuge", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themen", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Kosten", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Einstellungen", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Übersetzer", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/es.json b/src/i18n/messages/es.json index a2dfe6965b..ca90cb44bb 100644 --- a/src/i18n/messages/es.json +++ b/src/i18n/messages/es.json @@ -192,7 +192,9 @@ "themeCyan": "cian", "cliToolsShort": "Herramientas", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Temas", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Costos", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Configuración", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Traductor", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/fi.json b/src/i18n/messages/fi.json index 687476be1c..9ad44386cf 100644 --- a/src/i18n/messages/fi.json +++ b/src/i18n/messages/fi.json @@ -192,7 +192,9 @@ "themeCyan": "Syaani", "cliToolsShort": "Työkalut", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Teemat", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Kustannukset", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Asetukset", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Kääntäjä", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index b37abe59b2..f744e3e30b 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Outils", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Thèmes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Coûts", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Paramètres", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Traducteur", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/he.json b/src/i18n/messages/he.json index 2951d9ebbc..aafc4a504f 100644 --- a/src/i18n/messages/he.json +++ b/src/i18n/messages/he.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "כלים", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "עלויות", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "הגדרות", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "מתרגם", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/hi.json b/src/i18n/messages/hi.json index 5da00122b9..1667f60311 100644 --- a/src/i18n/messages/hi.json +++ b/src/i18n/messages/hi.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "उपकरण", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "लागत", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "सेटिंग्स", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "अनुवादक", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/hu.json b/src/i18n/messages/hu.json index 4549c87be7..1695304149 100644 --- a/src/i18n/messages/hu.json +++ b/src/i18n/messages/hu.json @@ -192,7 +192,9 @@ "themeCyan": "Cián", "cliToolsShort": "Eszközök", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Témák", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Költségek", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Beállítások elemre", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Fordító", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/id.json b/src/i18n/messages/id.json index 1afbebe040..41fea96c21 100644 --- a/src/i18n/messages/id.json +++ b/src/i18n/messages/id.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Alat", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Biaya", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Pengaturan", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Penerjemah", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/it.json b/src/i18n/messages/it.json index f26506e6f4..7dc1758932 100644 --- a/src/i18n/messages/it.json +++ b/src/i18n/messages/it.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Strumenti", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Costi", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Impostazioni", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Traduttore", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/ja.json b/src/i18n/messages/ja.json index daf4a46df4..75004b4f64 100644 --- a/src/i18n/messages/ja.json +++ b/src/i18n/messages/ja.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "ツール", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "コスト", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "設定", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "翻訳者", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/ko.json b/src/i18n/messages/ko.json index 2db87f5453..2d1415a859 100644 --- a/src/i18n/messages/ko.json +++ b/src/i18n/messages/ko.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "도구", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "비용", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "설정", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "번역기", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/ms.json b/src/i18n/messages/ms.json index 3096e2e9b7..78ca66e671 100644 --- a/src/i18n/messages/ms.json +++ b/src/i18n/messages/ms.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Alat", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Kos", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "tetapan", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Penterjemah", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/nl.json b/src/i18n/messages/nl.json index a5171b25c9..958fa36671 100644 --- a/src/i18n/messages/nl.json +++ b/src/i18n/messages/nl.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Gereedschap", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Kosten", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Instellingen", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Vertaler", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/no.json b/src/i18n/messages/no.json index 5a37804933..7ad294752d 100644 --- a/src/i18n/messages/no.json +++ b/src/i18n/messages/no.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Verktøy", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Kostnader", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Innstillinger", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Oversetter", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/phi.json b/src/i18n/messages/phi.json index 3757198ac6..741974d135 100644 --- a/src/i18n/messages/phi.json +++ b/src/i18n/messages/phi.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Mga Tool", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Mga gastos", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Mga setting", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Tagasalin", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/pl.json b/src/i18n/messages/pl.json index 928c75d705..bd0e176eb6 100644 --- a/src/i18n/messages/pl.json +++ b/src/i18n/messages/pl.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Narzędzia", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Koszty", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Ustawienia", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Tłumacz", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/pt-BR.json b/src/i18n/messages/pt-BR.json index c792e5dc2b..f17e8d349d 100644 --- a/src/i18n/messages/pt-BR.json +++ b/src/i18n/messages/pt-BR.json @@ -1792,7 +1792,9 @@ "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", "statusDeactivated": "Desativado (Manual)", "statusBanned": "Banido / Sandbox Violation", - "statusCreditsExhausted": "Saldo Insuficiente" + "statusCreditsExhausted": "Saldo Insuficiente", + "modelsImported": "{count} models imported", + "close": "Close" }, "settings": { "title": "Configurações", @@ -2284,7 +2286,15 @@ "modelsDevInfo": "How It Works", "modelsDevInfoDesc": "models.dev is an open-source database of AI model specifications maintained by the SST/OpenCode team. It provides pricing, capabilities, context limits, and modalities for 4,000+ models across 100+ providers.", "modelsDevInfoResolution": "Pricing resolution order (highest priority first):", - "modelsDevInfoOrder": "User Override → models.dev → LiteLLM → Hardcoded Default" + "modelsDevInfoOrder": "User Override → models.dev → LiteLLM → Hardcoded Default", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "maintenance": "Maintenance" }, "translator": { "title": "Tradutor", @@ -3148,6 +3158,7 @@ "actions": "Actions", "deduplicatedRequests": "Requisições Desduplicadas", "savedCalls": "Chamadas API Poupadas", - "totalProcessed": "Total Processado" + "totalProcessed": "Total Processado", + "peakCached": "Peak cached" } } diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index 1274a8f333..9d43c803c2 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -1783,7 +1783,9 @@ "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", "statusDeactivated": "Desativado (Manual)", "statusBanned": "Banido / Sandbox Violation", - "statusCreditsExhausted": "Saldo Insuficiente" + "statusCreditsExhausted": "Saldo Insuficiente", + "modelsImported": "{count} models imported", + "close": "Close" }, "settings": { "title": "Configurações", @@ -2269,7 +2271,15 @@ "modelsDevInfo": "How It Works", "modelsDevInfoDesc": "models.dev is an open-source database of AI model specifications maintained by the SST/OpenCode team. It provides pricing, capabilities, context limits, and modalities for 4,000+ models across 100+ providers.", "modelsDevInfoResolution": "Pricing resolution order (highest priority first):", - "modelsDevInfoOrder": "User Override → models.dev → LiteLLM → Hardcoded Default" + "modelsDevInfoOrder": "User Override → models.dev → LiteLLM → Hardcoded Default", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "maintenance": "Maintenance" }, "translator": { "title": "Tradutor", @@ -3133,6 +3143,7 @@ "actions": "Actions", "deduplicatedRequests": "Requisições Desduplicadas", "savedCalls": "Chamadas API Poupadas", - "totalProcessed": "Total Processado" + "totalProcessed": "Total Processado", + "peakCached": "Peak cached" } } diff --git a/src/i18n/messages/ro.json b/src/i18n/messages/ro.json index c81ebc39f4..d22886e8e0 100644 --- a/src/i18n/messages/ro.json +++ b/src/i18n/messages/ro.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Instrumente", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Costuri", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Setări", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Traducător", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/sk.json b/src/i18n/messages/sk.json index 7c4d62951f..8a782ea3df 100644 --- a/src/i18n/messages/sk.json +++ b/src/i18n/messages/sk.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Nástroje", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "náklady", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Nastavenia", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Prekladateľ", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/sv.json b/src/i18n/messages/sv.json index b893eaed1b..fa5a1d4c05 100644 --- a/src/i18n/messages/sv.json +++ b/src/i18n/messages/sv.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Verktyg", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Kostnader", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Inställningar", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Översättare", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/th.json b/src/i18n/messages/th.json index 4cd7d51e28..6ecf8c4ac4 100644 --- a/src/i18n/messages/th.json +++ b/src/i18n/messages/th.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "เครื่องมือ", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "ธีมส์", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "ค่าใช้จ่าย", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "การตั้งค่า", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "นักแปล", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/tr.json b/src/i18n/messages/tr.json index a29ea87753..654b35152f 100644 --- a/src/i18n/messages/tr.json +++ b/src/i18n/messages/tr.json @@ -192,7 +192,9 @@ "themeCyan": "Camgöbeği", "cliToolsShort": "Araçlar", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Temalar", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Ücretsiz Yığın ($0)", - "templateFreeStackDesc": "Tüm ücretsiz sağlayıcılarda round-robin: Kiro (Claude), Qoder (5 model), Qwen (4 model), Gemini CLI. Sıfır maliyet, kodlama kesintisiz." + "templateFreeStackDesc": "Tüm ücretsiz sağlayıcılarda round-robin: Kiro (Claude), Qoder (5 model), Qwen (4 model), Gemini CLI. Sıfır maliyet, kodlama kesintisiz.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Maliyetler", @@ -1723,7 +1729,12 @@ "chatPathHint": "Standart dışı API'lere sahip sağlayıcılar için özel sohbet yolu (ör. /v4/chat/completions)", "modelsPathLabel": "Model Uç Noktası Yolu", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Doğrulama için özel model yolu (ör. /v4/models)" + "modelsPathHint": "Doğrulama için özel model yolu (ör. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Ayarlar", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Çeviri", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/uk-UA.json b/src/i18n/messages/uk-UA.json index d2a83be472..6632ccc09a 100644 --- a/src/i18n/messages/uk-UA.json +++ b/src/i18n/messages/uk-UA.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Інструменти", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Витрати", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Налаштування", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Перекладач", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/vi.json b/src/i18n/messages/vi.json index adfa3c59c2..6d10bcc033 100644 --- a/src/i18n/messages/vi.json +++ b/src/i18n/messages/vi.json @@ -192,7 +192,9 @@ "themeCyan": "Cyan", "cliToolsShort": "Công cụ", "cache": "Cache", - "cacheShort": "Cache" + "cacheShort": "Cache", + "memory": "Memory", + "skills": "Skills" }, "themesPage": { "title": "Themes", @@ -992,7 +994,11 @@ } }, "templateFreeStack": "Free Stack ($0)", - "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding." + "templateFreeStackDesc": "Round-robin across all free providers: Kiro (Claude), Qoder (5 models), Qwen (4 models), Gemini CLI. Zero cost, never stops coding.", + "auto": "Auto Combo", + "autoDesc": "Self-healing smart routing pool (Performance optimized)", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)" }, "costs": { "title": "Chi phí", @@ -1723,7 +1729,12 @@ "chatPathHint": "Custom chat path for providers with non-standard APIs (e.g. /v4/chat/completions)", "modelsPathLabel": "Models Endpoint Path", "modelsPathPlaceholder": "/models", - "modelsPathHint": "Custom models path for validation (e.g. /v4/models)" + "modelsPathHint": "Custom models path for validation (e.g. /v4/models)", + "modelsImported": "{count} models imported", + "close": "Close", + "statusDeactivated": "Deactivated (Manual)", + "statusBanned": "Banned / Sandbox Violation", + "statusCreditsExhausted": "Insufficient Balance / Quota Exhausted" }, "settings": { "title": "Cài đặt", @@ -2203,7 +2214,21 @@ "skillsComingSoon": "Skills marketplace coming soon.", "memorySkillsTitle": "Memory & Skills", "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "days": "Days", + "cacheCleared": "Cache cleared successfully", + "clearCacheFailed": "Failed to clear cache", + "adaptiveVolumeRouting": "Adaptive Volume Routing", + "adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.", + "lkgpToggleTitle": "Last Known Good Provider (LKGP)", + "lkgpToggleDesc": "When enabled, the router remembers which provider last served a successful response and tries it first on subsequent requests.", + "clearLkgpCache": "Clear LKGP Cache", + "lkgpCacheCleared": "LKGP cache cleared successfully", + "lkgpCacheClearFailed": "Failed to clear LKGP cache", + "lkgp": "LKGP Mode", + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "maintenance": "Maintenance", + "purgeExpiredLogs": "Purge Expired Logs", + "purgeLogsFailed": "Failed to purge logs" }, "translator": { "title": "Người phiên dịch", @@ -3064,6 +3089,61 @@ "model": "Model", "created": "Created", "expires": "Expires", - "actions": "Actions" + "actions": "Actions", + "peakCached": "Peak cached", + "deduplicatedRequests": "Deduplicated Requests", + "savedCalls": "Saved API Calls", + "totalProcessed": "Total Requests Processed" + }, + "memory": { + "title": "Memory Management", + "description": "View and manage stored memory entries", + "memories": "Memories", + "totalEntries": "Total Entries", + "tokensUsed": "Tokens Used", + "hitRate": "Hit Rate", + "loading": "Loading memories...", + "noMemories": "No memories found", + "search": "Search memories...", + "allTypes": "All Types", + "export": "Export", + "import": "Import", + "addMemory": "Add Memory", + "type": "Type", + "key": "Key", + "content": "Content", + "created": "Created", + "actions": "Actions", + "factual": "Factual", + "episodic": "Episodic", + "procedural": "Procedural", + "semantic": "Semantic" + }, + "skills": { + "title": "Skills", + "description": "Manage and monitor AI skills", + "skillsTab": "Skills", + "executionsTab": "Executions", + "sandboxTab": "Sandbox", + "loading": "Loading skills...", + "noSkills": "No skills found", + "noExecutions": "No executions found", + "enabled": "Enabled", + "disabled": "Disabled", + "version": "Version", + "tableDescription": "Description", + "skill": "Skill", + "status": "Status", + "duration": "Duration", + "time": "Time", + "sandboxConfig": "Sandbox Configuration", + "cpuLimit": "CPU Limit", + "cpuLimitDesc": "Maximum execution time per skill", + "memoryLimit": "Memory Limit", + "memoryLimitDesc": "Maximum memory allocation", + "timeout": "Timeout", + "timeoutDesc": "Maximum wait time for response", + "networkAccess": "Network Access", + "networkAccessDesc": "Allow outbound network requests" } } diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index cedab5608c..387ec862fd 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -63,8 +63,8 @@ "accountId": "账户 ID", "alias": "别名", "apiKeyId": "API 密钥 ID", - "apiKeyName": "API Key 名称", - "apiKeySecret": "API Key 密钥", + "apiKeyName": "API 密钥名称", + "apiKeySecret": "API 密钥密文", "authorization": "授权", "content-type": "内容类型", "content-length": "内容长度", @@ -114,10 +114,10 @@ "proxy_id": "代理 ID", "proxyId": "代理 ID", "connectionId": "连接 ID", - "resolveConnectionId": "解析 Connection ID", - "resolve_connection_id": "解析 Connection ID", - "scope_id": "范围 ID", - "scopeId": "范围 ID", + "resolveConnectionId": "解析连接 ID", + "resolve_connection_id": "解析连接 ID", + "scope_id": "作用域 ID", + "scopeId": "作用域 ID", "jwtSecret": "JWT 密钥", "keytar": "keytar", "better-sqlite3": "better-sqlite3", @@ -156,6 +156,8 @@ "playground": "演练场", "searchTools": "搜索工具", "agents": "智能体", + "memory": "记忆", + "skills": "技能", "docs": "文档", "issues": "问题反馈", "endpoints": "端点", @@ -238,9 +240,9 @@ "quickStartDesc": "4 个步骤快速上手:连接提供商、路由模型并监控全局运行情况。", "fullDocs": "完整文档", "step1Title": "1. 创建 API 密钥", - "step1Desc": "前往 <endpoint>Endpoint</endpoint> -> Registered Keys。为每个环境生成一个独立密钥。", + "step1Desc": "前往 <endpoint>端点</endpoint> -> 已注册密钥。为每个环境生成一个独立密钥。", "step2Title": "2. 连接提供商", - "step2Desc": "在 <providers>Providers</providers> 中添加账户。支持 OAuth、API Key 和免费套餐。", + "step2Desc": "在 <providers>提供商</providers> 中添加账户。支持 OAuth、API Key 和免费套餐。", "step3Title": "3. 配置客户端", "step3Desc": "在 IDE 或 API 客户端中将基本 URL 设置为 {url}。", "step4Title": "4. 监控与优化", @@ -831,6 +833,8 @@ "priorityDesc": "顺序回退:优先尝试模型 1,其次模型 2,以此类推", "weightedDesc": "按照权重百分比分配流量,并支持失败回退", "roundRobinDesc": "循环分发:每个请求按顺序轮到下一个模型", + "contextRelay": "上下文接力", + "contextRelayDesc": "在账户轮换时通过交接摘要保持会话连续性", "randomDesc": "均匀随机选择,失败后回退到剩余模型", "leastUsedDesc": "优先选择请求数最少的模型,随时间平衡负载", "costOptimizedDesc": "根据定价优先路由到最便宜的模型", @@ -842,6 +846,13 @@ "retryDelay": "重试延迟(毫秒)", "concurrencyPerModel": "每模型并发数", "queueTimeout": "排队超时(毫秒)", + "contextRelayHandoffThreshold": "交接阈值", + "contextRelayHandoffThresholdHelp": "当配额使用达到该阈值时,OmniRoute 会在当前活跃账户耗尽前生成结构化交接摘要。", + "contextRelayMaxMessages": "摘要最大消息数", + "contextRelayMaxMessagesHelp": "限制压缩进接力摘要中的最近历史消息数量。", + "contextRelaySummaryModel": "摘要模型", + "contextRelaySummaryModelHelp": "仅用于生成交接摘要的可选覆盖模型。留空则复用当前活跃的 combo 模型。", + "contextRelayProviderNote": "Context Relay 当前主要为 Codex 账户轮换生成交接摘要。与同一提供商的多个账户配合使用时,连续性效果最佳。", "advancedHint": "留空则使用全局默认值。这些设置会覆盖每个提供商的配置。", "moveUp": "上移", "moveDown": "下移", @@ -886,9 +897,9 @@ "example": "后台任务或批处理作业,优先考虑更低成本。" }, "strict-random": { - "when": "Use when you want perfectly even spread — each model used once before repeating.", - "avoid": "Avoid when models have different quality or latency and order matters.", - "example": "Example: Multiple accounts of the same model to distribute usage evenly." + "when": "适用于希望实现绝对均匀分配的场景,每个模型在重复前都会恰好使用一次。", + "avoid": "如果模型之间的质量或延迟差异较大,且调用顺序很重要,则不建议使用。", + "example": "例如:同一模型挂载多个账户,用于更均匀地分摊使用量。" } }, "advancedHelp": { @@ -984,15 +995,19 @@ "tip3": "适合批处理或后台任务等成本是主要指标的场景。" }, "strict-random": { - "title": "Shuffle deck distribution", - "description": "Each model is used exactly once per cycle before reshuffling.", - "tip1": "Use at least 2 models for meaningful distribution.", - "tip2": "Works best with equivalent-performance models.", - "tip3": "Ideal for load balancing across multiple API accounts." + "title": "洗牌池分配", + "description": "每轮中每个模型都会被恰好使用一次,然后再重新洗牌。", + "tip1": "至少使用 2 个模型,才能体现分配效果。", + "tip2": "最适合性能相近的模型。", + "tip3": "非常适合在多个 API 账户之间做负载均衡。" } }, "templateFreeStack": "免费栈($0)", - "templateFreeStackDesc": "在所有免费提供商之间进行轮询:Kiro(Claude)、Qoder(5 个模型)、Qwen(4 个模型)、Gemini CLI。零成本,编码不中断。" + "templateFreeStackDesc": "在所有免费提供商之间进行轮询:Kiro(Claude)、Qoder(5 个模型)、Qwen(4 个模型)、Gemini CLI。零成本,编码不中断。", + "auto": "自动组合", + "autoDesc": "自愈型智能路由池(性能优化)", + "lkgp": "LKGP 模式", + "lkgpDesc": "最后已知良好提供商(可预测的弹性)" }, "costs": { "title": "成本", @@ -1031,6 +1046,8 @@ "audioTranscriptionDesc": "将音频文件转录为文本(Whisper)", "textToSpeech": "文本转语音", "textToSpeechDesc": "将文本转换为自然语音", + "musicGeneration": "音乐生成", + "musicDesc": "通过 ComfyUI 生成音乐和音轨(Stable Audio、MusicGen)", "moderations": "内容审核", "moderationsDesc": "内容安全审核与分类", "responsesDesc": "适用于 Codex 和高级智能体工作流的 OpenAI Responses API", @@ -1543,6 +1560,7 @@ "chatCompletions": "聊天完成", "importingModels": "正在导入...", "importFromModels": "从 /models 导入", + "modelsImported": "已导入 {count} 个模型", "allModelsAlreadyImported": "所有模型已导入", "noNewModelsToImport": "没有新模型可导入 — 所有模型已在注册表或自定义模型列表中", "skippingExistingModels": "跳过 {count} 个已有模型", @@ -1564,6 +1582,7 @@ "importFailed": "导入失败", "noNewModelsAdded": "没有添加新模型。", "adding": "添加...", + "close": "关闭", "importingModelsTitle": "导入模型", "copyModel": "复制模型", "removeModel": "删除模型", @@ -1723,7 +1742,10 @@ "chatPathHint": "为非标准 API 的提供商自定义聊天路径(例如:/v4/chat/completions)", "modelsPathLabel": "模型端点路径", "modelsPathPlaceholder": "/models", - "modelsPathHint": "为验证流程自定义模型路径(例如:/v4/models)" + "modelsPathHint": "为验证流程自定义模型路径(例如:/v4/models)", + "statusDeactivated": "已停用(手动)", + "statusBanned": "已封禁 / 沙箱违规", + "statusCreditsExhausted": "余额不足 / 配额已耗尽" }, "settings": { "title": "设置", @@ -1746,6 +1768,46 @@ "enablePassword": "启用密码", "darkMode": "深色模式", "lightMode": "浅色模式", + "memoryTitle": "记忆", + "memoryDesc": "跨会话持久化对话记忆", + "memoryEnabled": "启用记忆", + "memoryEnabledDesc": "启用后,OmniRoute 会注入相关的历史上下文。", + "maxTokens": "最大 Tokens", + "retentionDays": "保留时长", + "recent": "最近", + "recentDesc": "按时间顺序的时间窗", + "semantic": "语义", + "semanticDesc": "向量搜索", + "hybrid": "混合", + "hybridDesc": "最近 + 语义", + "skillsTitle": "技能", + "skillsDesc": "供模型调用的工具", + "skillsEnabled": "启用技能", + "skillsEnabledDesc": "允许智能体触发函数。", + "skillsComingSoon": "技能市场即将推出。", + "memorySkillsTitle": "记忆与技能", + "memorySkillsDesc": "持久化上下文与能力", + "modelsDevTitle": "模型数据库", + "modelsDevDesc": "从 models.dev 自动同步定价、能力和规格", + "modelsDevEnabled": "启用 models.dev 同步", + "modelsDevEnabledDesc": "从开源的 models.dev 数据库获取模型定价、能力和规格", + "modelsDevInterval": "同步间隔", + "syncNow": "立即同步", + "syncing": "同步中...", + "lastSync": "上次同步", + "never": "从未", + "justNow": "刚才", + "modelsDevStats": "同步统计", + "modelsDevStatsDesc": "当前 models.dev 数据覆盖情况", + "providers": "提供商", + "modelsWithPricing": "已有定价的模型", + "capabilities": "能力", + "lastSyncCount": "上次同步数量", + "lastSyncFull": "上次完整同步", + "modelsDevInfo": "工作原理", + "modelsDevInfoDesc": "models.dev 是由 SST/OpenCode 团队维护的开源 AI 模型规格数据库,提供 100+ 提供商、4,000+ 模型的定价、能力、上下文限制和模态信息。", + "modelsDevInfoResolution": "定价解析顺序(优先级从高到低):", + "modelsDevInfoOrder": "用户覆盖 → models.dev → LiteLLM → 硬编码默认值", "systemTheme": "系统主题", "debugToggle": "启用调试模式", "sidebarVisibilityToggle": "显示侧边栏项目", @@ -1832,20 +1894,20 @@ "themeViolet": "紫色", "themeOrange": "橙色", "themeCyan": "青色", - "whitelabeling": "Branding", - "whitelabelingDesc": "Customize the application name and logo", - "appName": "Application Name", - "appNameDesc": "Display name shown in sidebar and browser tab", - "customLogo": "Custom Logo URL", - "customLogoDesc": "URL to your custom logo image", - "uploadLogo": "Upload Logo", - "resetLogo": "Reset to Default", - "logoPreview": "Preview", - "customFavicon": "Browser Favicon", - "customFaviconDesc": "URL to your custom favicon (shown in browser tab)", - "uploadFavicon": "Upload Favicon", - "resetFavicon": "Reset Favicon", - "faviconPreview": "Favicon Preview", + "whitelabeling": "品牌定制", + "whitelabelingDesc": "自定义应用名称和 Logo", + "appName": "应用名称", + "appNameDesc": "显示在侧边栏和浏览器标签页中的名称", + "customLogo": "自定义 Logo URL", + "customLogoDesc": "你的自定义 Logo 图片地址", + "uploadLogo": "上传 Logo", + "resetLogo": "恢复默认", + "logoPreview": "预览", + "customFavicon": "浏览器 Favicon", + "customFaviconDesc": "你的自定义 Favicon 地址(显示在浏览器标签页中)", + "uploadFavicon": "上传 Favicon", + "resetFavicon": "重置 Favicon", + "faviconPreview": "Favicon 预览", "flushCache": "刷新缓存", "flushing": "正在刷新...", "size": "尺寸", @@ -1860,7 +1922,7 @@ "globalSystemPrompt": "全局系统提示", "systemPromptDesc": "在代理级别注入所有请求", "saved": "已保存", - "systemPromptPlaceholder": "输入系统提示符注入所有请求...", + "systemPromptPlaceholder": "输入要注入所有请求的系统提示...", "systemPromptHint": "此提示会添加到每个请求的系统消息之前。用于全局说明、安全指南或响应格式规则。", "chars": "{count} 字符", "thinkingBudgetTitle": "思考预算", @@ -1868,9 +1930,9 @@ "passthrough": "直通", "passthroughDesc": "没有变化——客户控制思维预算", "auto": "自动", - "autoDesc": "放弃所有思考配置——让提供商决定", + "autoDesc": "丢弃所有思考配置,由提供商自行决定", "custom": "定制", - "customDesc": "为所有请求设置固定的令牌预算", + "customDesc": "为所有请求设置固定的 Token 预算", "adaptive": "自适应", "adaptiveDesc": "根据请求复杂性调整预算", "effortNone": "无(0 Tokens)", @@ -1895,39 +1957,39 @@ "errorOccurred": "发生错误", "updatePassword": "更新密码", "setPassword": "设置密码", - "apiEndpointProtection": "API端点保护", + "apiEndpointProtection": "API 端点保护", "requireAuthModels": "/models 需要 API 密钥", "requireAuthModelsDesc": "开启后,`/v1/models` 对未认证请求返回 404,从而阻止未授权用户发现模型。", "blockedProviders": "被阻止的提供商", "blockedProvidersDesc": "在 `/v1/models` 响应中隐藏指定提供商。被隐藏的提供商不会出现在模型列表中。", - "providersBlocked": "{count} 提供商被阻止/模型", - "blockProviderTitle": "区块 {provider}", - "unblockProviderTitle": "解锁 {provider}", + "providersBlocked": "{count} 个提供商/模型已屏蔽", + "blockProviderTitle": "屏蔽 {provider}", + "unblockProviderTitle": "取消屏蔽 {provider}", "cliFingerprint": "CLI 指纹匹配", "cliFingerprintDesc": "在代理请求时模拟原生 CLI 二进制的请求特征。会重新排列请求头和请求体字段,使其与官方 CLI 工具更一致,同时保留你的代理 IP。", "cliFingerprintEnabled": "已有 {count} 个提供商启用了 CLI 指纹", "enableFingerprintTitle": "为 {provider} 启用指纹", "disableFingerprintTitle": "为 {provider} 禁用指纹", "routingStrategy": "路由策略", - "routingAdvancedGuideTitle": "高级路线指导", - "routingAdvancedGuideHint1": "使用 Fill First 实现可预测的优先级,使用 Round Robin 实现公平性,使用 P2C 实现延迟弹性。", - "routingAdvancedGuideHint2": "如果提供商的质量/成本各不相同,请从“成本选择”开始进行后台工作,并从“最少使用”开始进行平衡磨损。", - "fillFirst": "先填写", - "fillFirstDesc": "按优先顺序使用帐户", - "roundRobin": "循环赛", - "roundRobinDesc": "循环浏览所有帐户", + "routingAdvancedGuideTitle": "高级路由指南", + "routingAdvancedGuideHint1": "需要可预测优先级时使用 Fill First,需要公平分配时使用 Round Robin,需要延迟弹性时使用 P2C。", + "routingAdvancedGuideHint2": "如果各提供商在质量或成本上差异明显,后台任务可优先考虑“成本优化”,需要均衡消耗时可从“最少使用”开始。", + "fillFirst": "优先填满", + "fillFirstDesc": "按优先级顺序使用账户", + "roundRobin": "轮询", + "roundRobinDesc": "在所有账户之间轮流分配", "p2c": "P2C", "p2cDesc": "随机选2个,使用更健康的一个", "random": "随机", - "randomDesc": "每个请求随机帐户", + "randomDesc": "每次请求随机选择账户", "leastUsed": "最少使用", - "leastUsedDesc": "选择最近最少使用的帐户", - "costOpt": "成本选择", - "costOptDesc": "更喜欢最便宜的可用帐户", + "leastUsedDesc": "优先选择最近使用最少的账户", + "costOpt": "成本优化", + "costOptDesc": "优先选择成本最低的可用账户", "strictRandom": "严格随机", "strictRandomDesc": "洗牌池模式:每个账户使用一次后再重新洗牌", "stickyLimit": "粘性限制", - "stickyLimitDesc": "切换前每个账户的通话次数", + "stickyLimitDesc": "切换前每个账户连续处理的请求次数", "modelAliases": "模型别名", "modelAliasesTitle": "模型别名", "modelAliasesDesc": "重新映射模型名称的通配符模式 • 使用 * 和 ?", @@ -1972,7 +2034,7 @@ "ipModeWhitelistPriority": "WL优先级", "addIpAddress": "添加IP地址", "ipAddressPlaceholder": "192.168.1.0/24 或 10.0.*.*", - "block": "+ 块", + "block": "+ 屏蔽", "allow": "+ 允许", "blocked": "已被阻止 ({count})", "allowed": "允许 ({count})", @@ -2015,6 +2077,8 @@ "comboStrategyAria": "组合策略", "priority": "优先级", "weighted": "加权", + "contextRelay": "上下文接力", + "contextRelayDesc": "在账户轮换发生时,采用优先级风格路由并自动执行上下文交接", "maxRetriesLabel": "最大重试次数", "retryDelayLabel": "重试延迟(毫秒)", "timeoutLabel": "超时(毫秒)", @@ -2035,30 +2099,34 @@ "maxNestingDepth": "最大嵌套深度", "concurrencyPerModel": "并发/模型", "queueTimeout": "队列超时(毫秒)", - "providerProfiles": "提供商简介", + "contextRelayHandoffThreshold": "交接阈值", + "contextRelayMaxMessages": "摘要最大消息数", + "contextRelaySummaryModel": "摘要模型", + "contextRelayProviderNote": "Context Relay 当前会为 Codex 账户生成交接摘要,并将这些值作为新的或未配置 combo 的全局默认值。", + "providerProfiles": "提供商策略配置", "providerProfilesDesc": "为 OAuth(基于会话)和 API Key(计费型)提供商分别设置弹性策略。由于速率限制更低,OAuth 提供商通常采用更严格的阈值。", "oauthProviders": "OAuth 提供商", "apiKeyProviders": "API 密钥提供商", - "transientCooldown": "短暂冷却", - "rateLimitCooldown": "速率限制冷却", + "transientCooldown": "瞬时故障冷却", + "rateLimitCooldown": "限流冷却", "maxBackoffLevel": "最大退避级别", - "cbThreshold": "CB阈值", - "cbResetTime": "CB 复位时间", + "cbThreshold": "熔断阈值", + "cbResetTime": "熔断重置时间", "rateLimiting": "速率限制", "rateLimitingDesc": "API 密钥提供商会自动受到安全默认值的速率限制。限制是从响应标头中学习的,并随着时间的推移进行调整。", "defaultSafetyNet": "默认安全网", - "rpm": "转速", - "minGap": "最小间隙", + "rpm": "RPM", + "minGap": "最小间隔", "maxConcurrent": "最大并发数", - "activeLimiters": "有源限制器", + "activeLimiters": "活动限流器", "noActiveLimiters": "尚无活动的速率限制器。", - "reservoir": "水库", + "reservoir": "令牌池", "running": "运行中", "queued": "排队中", "circuitBreakers": "断路器", - "breakerStateClosed": "关闭", - "breakerStateOpen": "打开", - "breakerStateHalfOpen": "半开式", + "breakerStateClosed": "闭合", + "breakerStateOpen": "断开", + "breakerStateHalfOpen": "半开", "tripped": "{count} 已触发", "healthy": "{count} 健康", "resetAll": "全部重置", @@ -2108,9 +2176,8 @@ "exportFailedWithError": "导出失败:{error}", "fullExportFailedWithError": "完全导出失败:{error}", "backupCreated": "创建备份:{file}", - "restoreSuccess": "恢复了! {connections} 连接、{nodes} 节点、{combos} 组合、{apiKeys} API 密钥。", - "importSuccess": "数据库导入! {connections} 连接、{nodes} 节点、{combos} 组合、{apiKeys} API 密钥。", - "justNow": "刚才", + "restoreSuccess": "恢复完成!共恢复 {connections} 个连接、{nodes} 个节点、{combos} 个组合、{apiKeys} 个 API 密钥。", + "importSuccess": "数据库导入完成!共导入 {connections} 个连接、{nodes} 个节点、{combos} 个组合、{apiKeys} 个 API 密钥。", "minutesAgo": "{count} 分钟前", "hoursAgo": "{count} 小时前", "daysAgo": "{count} 天前", @@ -2125,7 +2192,6 @@ "errorDuringImport": "导入时发生错误", "modelPricing": "模型定价", "modelPricingDesc": "配置每个模型的成本费率 • 所有费率均以美元/100 万 Tokens 为单位", - "providers": "提供商", "registry": "登记处", "priced": "定价", "searchProvidersModels": "搜索提供商或模型...", @@ -2139,7 +2205,7 @@ "model": "模型", "models": "模型", "moreProviders": "{count} 更多提供商", - "withPricing": "配置定价", + "withPricing": "已配置定价", "policiesCircuitBreakers": "策略与断路器", "activeIssuesDetected": "检测到活跃问题", "off": "关闭", @@ -2147,7 +2213,7 @@ "pricingDescInput": "输入:发送到模型的令牌", "pricingDescOutput": "输出:生成的 Tokens", "pricingDescCached": "缓存:重用输入(约输入率的 50%)", - "pricingDescReasoning": "推理:思考标记(回到输出)", + "pricingDescReasoning": "推理:思考 Tokens(默认回退到输出费率)", "pricingDescCacheWrite": "缓存写入:创建缓存条目(回退到输入)", "pricingDescFormula": "成本 = (输入 × 输入率) + (输出 × 输出率) + (缓存 × 缓存率) 每百万 Tokens。", "pricingSettingsTitle": "定价设置", @@ -2158,11 +2224,11 @@ "pricingFormat": "定价格式", "pricingFormatDesc": "所有费率均以美元/100 万 Tokens 为单位(每百万 Tokens 美元)。", "tokenTypes": "Token 类型", - "inputTokenDesc": "标准提示标记", - "outputTokenDesc": "完成/响应标记", - "cachedTokenDesc": "缓存输入令牌(通常为输入速率的 50%)", - "reasoningTokenDesc": "特殊推理/思维标记(回退到输出率)", - "cacheCreationTokenDesc": "用于创建缓存条目的令牌(回退到输入速率)", + "inputTokenDesc": "标准提示 Tokens", + "outputTokenDesc": "补全 / 响应 Tokens", + "cachedTokenDesc": "缓存输入 Tokens(通常按输入费率的 50% 计)", + "reasoningTokenDesc": "特殊推理 / 思考 Tokens(回退到输出费率)", + "cacheCreationTokenDesc": "用于创建缓存条目的 Tokens(回退到输入费率)", "customPricingNote": "你可以覆盖特定模型的默认定价。自定义覆盖会优先于自动检测到的定价。", "editPricing": "编辑定价", "viewFullDetails": "查看完整详情", @@ -2174,54 +2240,18 @@ "clearLkgpCache": "清除 LKGP 缓存", "lkgpCacheCleared": "LKGP 缓存已成功清除", "lkgpCacheClearFailed": "清除 LKGP 缓存失败", + "days": "天", + "lkgp": "LKGP 模式", + "lkgpDesc": "最后已知良好提供商(可预测的弹性)", "maintenance": "维护", "purgeExpiredLogs": "清理过期日志", - "purgeLogsFailed": "清理日志失败", - "modelsDevTitle": "Model Database", - "modelsDevDesc": "Auto-sync pricing, capabilities & specs from models.dev", - "modelsDevEnabled": "Enable models.dev Sync", - "modelsDevEnabledDesc": "Fetch model pricing, capabilities, and specs from the open-source models.dev database", - "modelsDevInterval": "Sync Interval", - "syncNow": "Sync Now", - "syncing": "Syncing...", - "lastSync": "Last sync", - "never": "Never", - "modelsDevStats": "Sync Statistics", - "modelsDevStatsDesc": "Current models.dev data coverage", - "modelsWithPricing": "Models with Pricing", - "capabilities": "Capabilities", - "lastSyncCount": "Last Sync Count", - "lastSyncFull": "Last full sync", - "modelsDevInfo": "How It Works", - "modelsDevInfoDesc": "models.dev is an open-source database of AI model specifications maintained by the SST/OpenCode team. It provides pricing, capabilities, context limits, and modalities for 4,000+ models across 100+ providers.", - "modelsDevInfoResolution": "Pricing resolution order (highest priority first):", - "modelsDevInfoOrder": "User Override → models.dev → LiteLLM → Hardcoded Default", - "memoryTitle": "Memory", - "memoryDesc": "Persistent cross-session conversational memory", - "memoryEnabled": "Enable Memory", - "memoryEnabledDesc": "When enabled, OmniRoute will inject relevant past context.", - "maxTokens": "Max Tokens", - "retentionDays": "Retention", - "recent": "Recent", - "recentDesc": "Chronological window", - "semantic": "Semantic", - "semanticDesc": "Vector search", - "hybrid": "Hybrid", - "hybridDesc": "Recent + Semantic", - "skillsTitle": "Skills", - "skillsDesc": "Tools for models", - "skillsEnabled": "Enable Skills", - "skillsEnabledDesc": "Allows agents to trigger functions.", - "skillsComingSoon": "Skills marketplace coming soon.", - "memorySkillsTitle": "Memory & Skills", - "memorySkillsDesc": "Persistent context & capabilities", - "days": "Days" + "purgeLogsFailed": "清理日志失败" }, "translator": { - "title": "翻译者", - "metaTitle": "翻译游乐场 | OmniRoute", + "title": "翻译器", + "metaTitle": "翻译器游乐场 | OmniRoute", "metaDescription": "调试、测试和可视化提供商之间的 API 格式转换", - "playgroundTitle": "翻译游乐场", + "playgroundTitle": "翻译器游乐场", "playground": "游乐场", "realtime": "实时翻译活动", "chatTester": "聊天测试仪", @@ -2408,7 +2438,7 @@ "circuitBreakers": "断路器", "lockedIPs": "锁定IP", "lockoutsAutoRefreshHint": "每个模型速率限制锁定 • 自动刷新 10 秒", - "lockedCount": "{count, plural, one {# 个锁定} other {# 个锁定}}", + "lockedCount": "{count, plural, one {# 个锁定项} other {# 个锁定项}}", "timeLeft": "剩余 {time}", "howItWorks": "工作原理", "howItWorksSubtitle": "了解评估如何验证您的 LLM 回答", @@ -2641,7 +2671,11 @@ "waitingForOpenAIAuthorization": "正在等待 OpenAI 授权...", "waitingForAntigravityAuthorization": "正在等待 Antigravity 授权...", "waitingForQoderAuthorization": "正在等待 Qoder 授权...", - "exchangingCodeForTokens": "正在用授权码换取 Tokens..." + "exchangingCodeForTokens": "正在用授权码换取 Tokens...", + "nodeIncompatibleTitle": "不兼容的 Node.js 版本", + "nodeIncompatibleDesc": "你当前运行的是 Node.js {version},它与 OmniRoute 不兼容。原生 SQLite 模块(better-sqlite3)要求使用 Node.js 18–22 LTS。", + "nodeIncompatibleFixLabel": "修复:安装 Node.js 22 LTS", + "nodeIncompatibleHint": "OmniRoute 要求 Node.js ≥18 且 <24。为保证稳定性,建议使用 Node 22 LTS。" }, "landing": { "brandName": "OmniRoute", @@ -3065,6 +3099,7 @@ "cachedTokensCol": "已缓存", "cacheCreation": "创建", "trend24h": "缓存趋势(24 小时)", + "peakCached": "峰值缓存量", "cached": "已缓存", "overview": "概览", "entries": "条目", @@ -3076,6 +3111,60 @@ "model": "模型", "created": "创建时间", "expires": "到期时间", - "actions": "操作" + "actions": "操作", + "deduplicatedRequests": "去重请求数", + "savedCalls": "节省的 API 调用次数", + "totalProcessed": "已处理请求总数" + }, + "memory": { + "title": "记忆管理", + "description": "查看并管理已存储的记忆条目", + "memories": "记忆", + "totalEntries": "总条目数", + "tokensUsed": "已用 Tokens", + "hitRate": "命中率", + "loading": "正在加载记忆...", + "noMemories": "未找到记忆条目", + "search": "搜索记忆...", + "allTypes": "全部类型", + "export": "导出", + "import": "导入", + "addMemory": "添加记忆", + "type": "类型", + "key": "键", + "content": "内容", + "created": "创建时间", + "actions": "操作", + "factual": "事实型", + "episodic": "情景型", + "procedural": "程序型", + "semantic": "语义型" + }, + "skills": { + "title": "技能", + "description": "管理并监控 AI 技能", + "skillsTab": "技能", + "executionsTab": "执行记录", + "sandboxTab": "沙箱", + "loading": "正在加载技能...", + "noSkills": "未找到技能", + "noExecutions": "未找到执行记录", + "enabled": "已启用", + "disabled": "已禁用", + "version": "版本", + "tableDescription": "说明", + "skill": "技能", + "status": "状态", + "duration": "耗时", + "time": "时间", + "sandboxConfig": "沙箱配置", + "cpuLimit": "CPU 限制", + "cpuLimitDesc": "单个技能允许的最长执行时间", + "memoryLimit": "内存限制", + "memoryLimitDesc": "允许分配的最大内存", + "timeout": "超时", + "timeoutDesc": "等待响应的最长时间", + "networkAccess": "网络访问", + "networkAccessDesc": "允许发起出站网络请求" } } diff --git a/src/lib/a2a/skills/quotaManagement.ts b/src/lib/a2a/skills/quotaManagement.ts index 354071540f..3c8b720520 100644 --- a/src/lib/a2a/skills/quotaManagement.ts +++ b/src/lib/a2a/skills/quotaManagement.ts @@ -7,8 +7,9 @@ import type { A2ATask, TaskArtifact } from "../taskManager"; import { normalizeQuotaResponse } from "@/shared/contracts/quota"; +import { resolveOmniRouteBaseUrl } from "@/shared/utils/resolveOmniRouteBaseUrl"; -const OMNIROUTE_BASE_URL = process.env.OMNIROUTE_BASE_URL || "http://localhost:20128"; +const OMNIROUTE_BASE_URL = resolveOmniRouteBaseUrl(); const OMNIROUTE_API_KEY = process.env.OMNIROUTE_API_KEY || ""; async function quotaFetch(path: string): Promise<any> { diff --git a/src/lib/a2a/skills/smartRouting.ts b/src/lib/a2a/skills/smartRouting.ts index a086f62e95..4f8d0bec95 100644 --- a/src/lib/a2a/skills/smartRouting.ts +++ b/src/lib/a2a/skills/smartRouting.ts @@ -6,8 +6,9 @@ */ import type { A2ATask, TaskArtifact } from "../taskManager"; +import { resolveOmniRouteBaseUrl } from "@/shared/utils/resolveOmniRouteBaseUrl"; -const OMNIROUTE_BASE_URL = process.env.OMNIROUTE_BASE_URL || "http://localhost:20128"; +const OMNIROUTE_BASE_URL = resolveOmniRouteBaseUrl(); const OMNIROUTE_API_KEY = process.env.OMNIROUTE_API_KEY || ""; async function routeFetch(path: string, options: RequestInit = {}): Promise<any> { diff --git a/src/lib/oauth/constants/oauth.ts b/src/lib/oauth/constants/oauth.ts index 7d68a05b34..d6c3c9127c 100644 --- a/src/lib/oauth/constants/oauth.ts +++ b/src/lib/oauth/constants/oauth.ts @@ -1,15 +1,15 @@ /** * OAuth Configuration Constants * - * Credentials read from env vars with hardcoded fallbacks. - * The hardcoded values are the application's built-in credentials - * used when users log in via the UI for the first time. - * Override via env vars or provider-credentials.json for custom setups. + * All credentials are read exclusively from environment variables. + * Default values are provided via .env.example and auto-populated by + * scripts/sync-env.mjs on install. See .env.example for the built-in + * credentials used for localhost setups. */ // Claude OAuth Configuration (Authorization Code Flow with PKCE) export const CLAUDE_CONFIG = { - clientId: process.env.CLAUDE_OAUTH_CLIENT_ID || "9d1c250a-e61b-44d9-88ed-5944d1962f5e", + clientId: process.env.CLAUDE_OAUTH_CLIENT_ID || "", authorizeUrl: "https://claude.ai/oauth/authorize", tokenUrl: "https://console.anthropic.com/v1/oauth/token", redirectUri: @@ -26,7 +26,7 @@ export const CLAUDE_CONFIG = { // Codex (OpenAI) OAuth Configuration (Authorization Code Flow with PKCE) export const CODEX_CONFIG = { - clientId: process.env.CODEX_OAUTH_CLIENT_ID || "app_EMoamEEZ73f0CkXaXp7hrann", + clientId: process.env.CODEX_OAUTH_CLIENT_ID || "", authorizeUrl: "https://auth.openai.com/oauth/authorize", tokenUrl: "https://auth.openai.com/oauth/token", scope: "openid profile email offline_access", @@ -41,10 +41,9 @@ export const CODEX_CONFIG = { // Gemini (Google) OAuth Configuration (Standard OAuth2) export const GEMINI_CONFIG = { - clientId: - process.env.GEMINI_OAUTH_CLIENT_ID || - "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com", - clientSecret: process.env.GEMINI_OAUTH_CLIENT_SECRET || "", + clientId: process.env.GEMINI_CLI_OAUTH_CLIENT_ID || process.env.GEMINI_OAUTH_CLIENT_ID || "", + clientSecret: + process.env.GEMINI_CLI_OAUTH_CLIENT_SECRET || process.env.GEMINI_OAUTH_CLIENT_SECRET || "", authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth", tokenUrl: "https://oauth2.googleapis.com/token", userInfoUrl: "https://www.googleapis.com/oauth2/v1/userinfo", @@ -57,7 +56,7 @@ export const GEMINI_CONFIG = { // Qwen OAuth Configuration (Device Code Flow with PKCE) export const QWEN_CONFIG = { - clientId: process.env.QWEN_OAUTH_CLIENT_ID || "f0304373b74a44d2b584a3fb70ca9e56", + clientId: process.env.QWEN_OAUTH_CLIENT_ID || "", deviceCodeUrl: "https://chat.qwen.ai/api/v1/oauth2/device/code", tokenUrl: "https://chat.qwen.ai/api/v1/oauth2/token", scope: "openid profile email model.completion", @@ -92,7 +91,7 @@ export const QODER_CONFIG = { // Kimi Coding OAuth Configuration (Device Code Flow) export const KIMI_CODING_CONFIG = { - clientId: process.env.KIMI_CODING_OAUTH_CLIENT_ID || "17e5f671-d194-4dfb-9706-5516cb48c098", + clientId: process.env.KIMI_CODING_OAUTH_CLIENT_ID || "", deviceCodeUrl: "https://auth.kimi.com/api/oauth/device_authorization", tokenUrl: "https://auth.kimi.com/api/oauth/token", }; @@ -115,11 +114,8 @@ export const CLINE_CONFIG = { // Antigravity OAuth Configuration (Standard OAuth2 with Google) export const ANTIGRAVITY_CONFIG = { - clientId: - process.env.ANTIGRAVITY_OAUTH_CLIENT_ID || - "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com", - clientSecret: - process.env.ANTIGRAVITY_OAUTH_CLIENT_SECRET || "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", + clientId: process.env.ANTIGRAVITY_OAUTH_CLIENT_ID || "", + clientSecret: process.env.ANTIGRAVITY_OAUTH_CLIENT_SECRET || "", authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth", tokenUrl: "https://oauth2.googleapis.com/token", userInfoUrl: "https://www.googleapis.com/oauth2/v1/userinfo", @@ -142,7 +138,7 @@ export const ANTIGRAVITY_CONFIG = { // OpenAI OAuth Configuration (Authorization Code Flow with PKCE) export const OPENAI_CONFIG = { - clientId: process.env.CODEX_OAUTH_CLIENT_ID || "app_EMoamEEZ73f0CkXaXp7hrann", + clientId: process.env.CODEX_OAUTH_CLIENT_ID || "", authorizeUrl: "https://auth.openai.com/oauth/authorize", tokenUrl: "https://auth.openai.com/oauth/token", scope: "openid profile email offline_access", @@ -155,7 +151,7 @@ export const OPENAI_CONFIG = { // GitHub Copilot OAuth Configuration (Device Code Flow) export const GITHUB_CONFIG = { - clientId: process.env.GITHUB_OAUTH_CLIENT_ID || "Iv1.b507a08c87ecfe98", + clientId: process.env.GITHUB_OAUTH_CLIENT_ID || "", deviceCodeUrl: "https://github.com/login/device/code", tokenUrl: "https://github.com/login/oauth/access_token", userInfoUrl: "https://api.github.com/user", diff --git a/src/lib/oauth/providers/gemini.ts b/src/lib/oauth/providers/gemini.ts index 6375050c4e..3ed3491303 100644 --- a/src/lib/oauth/providers/gemini.ts +++ b/src/lib/oauth/providers/gemini.ts @@ -28,16 +28,14 @@ export const gemini = { } else { // (#537) Google's OAuth2 token endpoint always requires client_secret for // non-PKCE flows. Without it we get a cryptic "client_secret is missing" error. - const envName = config.clientId.includes("cli") - ? "GEMINI_CLI_OAUTH_CLIENT_SECRET" - : "GEMINI_OAUTH_CLIENT_SECRET"; + const envName = "GEMINI_CLI_OAUTH_CLIENT_SECRET or GEMINI_OAUTH_CLIENT_SECRET"; throw new Error( `Gemini OAuth requires ${envName} to be set.\n` + `In Docker: add '${envName}=<your-secret>' to your docker-compose.yml env.\n` + "In npm: add it to ~/.omniroute/.env\n" + "Obtain the client secret from https://console.cloud.google.com/apis/credentials\n" + - "for the same OAuth 2.0 Client ID configured as GEMINI_OAUTH_CLIENT_ID." + "for the same OAuth 2.0 Client ID configured as GEMINI_CLI_OAUTH_CLIENT_ID or GEMINI_OAUTH_CLIENT_ID." ); } diff --git a/src/lib/system/autoUpdate.ts b/src/lib/system/autoUpdate.ts index 8481f0398b..1bf071fe45 100644 --- a/src/lib/system/autoUpdate.ts +++ b/src/lib/system/autoUpdate.ts @@ -7,7 +7,7 @@ import { promisify } from "node:util"; const execFileAsync = promisify(execFile); type ComposeCommand = "docker compose" | "docker-compose"; -export type AutoUpdateMode = "npm" | "docker-compose"; +export type AutoUpdateMode = "npm" | "docker-compose" | "source"; type ExecFileLike = typeof execFileAsync; type SpawnLike = typeof spawn; @@ -38,7 +38,10 @@ export type AutoUpdateLaunchResult = { }; function normalizeMode(raw: string | undefined): AutoUpdateMode { - return raw === "docker-compose" ? "docker-compose" : "npm"; + if (raw === "docker-compose" || raw === "source") { + return raw; + } + return "npm"; } async function pathExists(targetPath: string): Promise<boolean> { @@ -74,7 +77,7 @@ export function getAutoUpdateConfig(env: NodeJS.ProcessEnv = process.env): AutoU // If we are not in a global node_modules directory, we are likely a local source install/build. // Even if .git is missing (downloaded zip), we should treat it as source. if (isGitRepo || !isGlobalNodeModules) { - mode = "source" as any; + mode = "source"; } } @@ -113,11 +116,29 @@ export async function validateAutoUpdateRuntime( execFileImpl: ExecFileLike = execFileAsync, existsImpl: (targetPath: string) => Promise<boolean> = pathExists ): Promise<AutoUpdateValidation> { - if (config.mode === ("source" as any)) { + if (config.mode === "source") { + const gitDir = path.join(process.cwd(), ".git"); + if (!(await existsImpl(gitDir))) { + return { + supported: false, + reason: "Not a git repository. Download source or use npm install -g.", + composeCommand: null, + }; + } + + try { + await execFileImpl("git", ["--version"], { timeout: 10_000 }); + } catch { + return { + supported: false, + reason: "git is not available. Install git to enable auto-update.", + composeCommand: null, + }; + } + return { - supported: false, - reason: - "Manual 'git pull && npm install && npm run build' is required for source installations.", + supported: true, + reason: null, composeCommand: null, }; } @@ -173,6 +194,21 @@ export async function validateAutoUpdateRuntime( return { supported: true, reason: null, composeCommand }; } +export async function ensureGitTagExists( + targetTag: string, + execFileImpl: ExecFileLike = execFileAsync, + cwd = process.cwd() +): Promise<void> { + try { + await execFileImpl("git", ["rev-parse", "-q", "--verify", `refs/tags/${targetTag}`], { + timeout: 10_000, + cwd, + }); + } catch { + throw new Error(`Git tag not found: ${targetTag}`); + } +} + export function buildNpmUpdateScript(latest: string): string { return [ "set -eu", @@ -184,6 +220,30 @@ export function buildNpmUpdateScript(latest: string): string { ].join("\n"); } +export function buildSourceUpdateScript(latest: string, gitRemote = "origin"): string { + const targetTag = latest.startsWith("v") ? latest : `v${latest}`; + + return [ + "set -eu", + "git stash --include-untracked 2>/dev/null || true", + `git fetch --tags ${shellQuote(gitRemote)}`, + `if ! git rev-parse -q --verify "refs/tags/${targetTag}" >/dev/null 2>&1; then`, + ` echo "[AutoUpdate] Tag ${targetTag} not found." >&2`, + " exit 1", + "fi", + 'backup_branch="pre-update/$(git rev-parse --short HEAD)-$(date +%Y%m%d-%H%M%S)"', + 'git branch "$backup_branch" 2>/dev/null || true', + `git checkout "${targetTag}"`, + "npm install --legacy-peer-deps", + "node scripts/sync-env.mjs 2>/dev/null || true", + "npm run build", + "if command -v pm2 >/dev/null 2>&1; then", + " pm2 restart omniroute --update-env || true", + "fi", + `echo "[AutoUpdate] Successfully updated to ${targetTag}."`, + ].join("\n"); +} + export function buildDockerComposeUpdateScript({ latest, config, @@ -237,14 +297,16 @@ export async function launchAutoUpdate({ env = process.env, execFileImpl = execFileAsync, spawnImpl = spawn, + existsImpl = pathExists, }: { latest: string; env?: NodeJS.ProcessEnv; execFileImpl?: ExecFileLike; spawnImpl?: SpawnLike; + existsImpl?: (targetPath: string) => Promise<boolean>; }): Promise<AutoUpdateLaunchResult> { const config = getAutoUpdateConfig(env); - const validation = await validateAutoUpdateRuntime(config, execFileImpl); + const validation = await validateAutoUpdateRuntime(config, execFileImpl, existsImpl); if (!validation.supported) { return { @@ -263,7 +325,9 @@ export async function launchAutoUpdate({ config, composeCommand: validation.composeCommand || "docker-compose", }) - : buildNpmUpdateScript(latest); + : config.mode === "source" + ? buildSourceUpdateScript(latest, config.gitRemote) + : buildNpmUpdateScript(latest); mkdirSync(path.dirname(config.logPath), { recursive: true }); const logFd = openSync(config.logPath, "a"); diff --git a/src/mitm/server.cjs b/src/mitm/server.cjs index e8a3f8be05..62f2dfc9d4 100644 --- a/src/mitm/server.cjs +++ b/src/mitm/server.cjs @@ -15,7 +15,14 @@ function getDataDir() { // Configuration const TARGET_HOST = "daily-cloudcode-pa.googleapis.com"; const LOCAL_PORT = 443; -const ROUTER_URL = "http://localhost:20128/v1/chat/completions"; +const ROUTER_BASE_URL = ( + process.env.OMNIROUTE_BASE_URL || + process.env.BASE_URL || + "http://localhost:20128" +) + .trim() + .replace(/\/+$/, ""); +const ROUTER_URL = `${ROUTER_BASE_URL}/v1/chat/completions`; const API_KEY = process.env.ROUTER_API_KEY; const DATA_DIR = getDataDir(); const DB_FILE = path.join(DATA_DIR, "db.json"); diff --git a/src/shared/components/OAuthModal.tsx b/src/shared/components/OAuthModal.tsx index 66b0c7b0b5..356a39899d 100644 --- a/src/shared/components/OAuthModal.tsx +++ b/src/shared/components/OAuthModal.tsx @@ -128,7 +128,7 @@ export default function OAuthModal({ "For remote use, configure your own OAuth credentials via environment variables: " + (provider === "antigravity" ? "ANTIGRAVITY_OAUTH_CLIENT_ID and ANTIGRAVITY_OAUTH_CLIENT_SECRET" - : "GEMINI_OAUTH_CLIENT_ID and GEMINI_OAUTH_CLIENT_SECRET") + + : "GEMINI_CLI_OAUTH_CLIENT_ID and GEMINI_CLI_OAUTH_CLIENT_SECRET") + ". See the README section 'OAuth on a Remote Server'." ); } else { diff --git a/src/shared/utils/logger.ts b/src/shared/utils/logger.ts index edb2874200..87916031ef 100644 --- a/src/shared/utils/logger.ts +++ b/src/shared/utils/logger.ts @@ -104,10 +104,11 @@ function buildLogger(): pino.Logger { }); } catch (err) { // Log the actual error for diagnostics (issue #165) - console.warn( - "[logger] Failed to set up file transport, attempting sync fallback...", - (err as Error)?.message || err - ); + try { + process.stderr.write( + `[logger] Failed to set up file transport, attempting sync fallback: ${(err as Error)?.message || err}\n` + ); + } catch {} // Fallback: use sync pino.destination() instead of worker-thread transport // pino.transport() uses worker threads which can fail in Next.js production bundles @@ -124,10 +125,11 @@ function buildLogger(): pino.Logger { ]) ); } catch (fallbackErr) { - console.warn( - "[logger] Sync fallback also failed, falling back to console only", - (fallbackErr as Error)?.message || fallbackErr - ); + try { + process.stderr.write( + `[logger] Sync fallback also failed, falling back to console only: ${(fallbackErr as Error)?.message || fallbackErr}\n` + ); + } catch {} } } } diff --git a/src/shared/utils/maskEmail.ts b/src/shared/utils/maskEmail.ts new file mode 100644 index 0000000000..eb61f5914e --- /dev/null +++ b/src/shared/utils/maskEmail.ts @@ -0,0 +1,36 @@ +/** + * maskEmail — Privacy display utility for email addresses. + * + * Masks the username and domain name portions of an email address + * to prevent identity exposure in dashboards and logs. + * + * @example + * maskEmail("diego.souza@gmail.com") // "di*********@g****.com" + * maskEmail("a@b.com") // "a@b.com" (too short to mask) + */ +export function maskEmail(email: string | null | undefined, visibleChars = 2): string { + if (!email) return ""; + if (!email.includes("@")) return email; + + const atIndex = email.lastIndexOf("@"); + const username = email.slice(0, atIndex); + const rest = email.slice(atIndex + 1); // "gmail.com", "co.uk", etc. + + const dotIndex = rest.indexOf("."); + const domainName = dotIndex !== -1 ? rest.slice(0, dotIndex) : rest; + const tld = dotIndex !== -1 ? rest.slice(dotIndex) : ""; // ".com", ".co.uk" + + // If username is too short to mask meaningfully, return as-is + if (username.length <= visibleChars) return email; + + const maskedUser = + username.slice(0, visibleChars) + "*".repeat(username.length - visibleChars); + + // Mask domain name: keep first char, mask the rest + const maskedDomain = + domainName.length > 1 + ? domainName.slice(0, 1) + "*".repeat(domainName.length - 1) + : domainName; + + return `${maskedUser}@${maskedDomain}${tld}`; +} diff --git a/src/shared/utils/resolveOmniRouteBaseUrl.ts b/src/shared/utils/resolveOmniRouteBaseUrl.ts new file mode 100644 index 0000000000..3f4c18f33b --- /dev/null +++ b/src/shared/utils/resolveOmniRouteBaseUrl.ts @@ -0,0 +1,24 @@ +const DEFAULT_OMNIROUTE_BASE_URL = "http://localhost:20128"; + +type OmniRouteBaseUrlEnv = { + OMNIROUTE_BASE_URL?: string; + BASE_URL?: string; + NEXT_PUBLIC_BASE_URL?: string; +}; + +function normalizeBaseUrl(value?: string): string | null { + const trimmed = value?.trim(); + if (!trimmed) return null; + return trimmed.replace(/\/+$/, ""); +} + +export function resolveOmniRouteBaseUrl(env: OmniRouteBaseUrlEnv = process.env): string { + return ( + normalizeBaseUrl(env.OMNIROUTE_BASE_URL) || + normalizeBaseUrl(env.BASE_URL) || + normalizeBaseUrl(env.NEXT_PUBLIC_BASE_URL) || + DEFAULT_OMNIROUTE_BASE_URL + ); +} + +export { DEFAULT_OMNIROUTE_BASE_URL }; diff --git a/src/shared/utils/structuredLogger.ts b/src/shared/utils/structuredLogger.ts index c6d2bd03ba..f6e9135b2f 100644 --- a/src/shared/utils/structuredLogger.ts +++ b/src/shared/utils/structuredLogger.ts @@ -105,6 +105,42 @@ function buildEntry( return entry; } +// EPIPE-safe error deduplication + rate limiting (#1006) +const _recentErrors = new Map<string, { count: number; firstSeen: number }>(); +const DEDUP_WINDOW_MS = 5_000; +const MAX_WRITES_PER_SECOND = 50; +let _writeCount = 0; +let _writeWindowStart = Date.now(); + +function shouldSuppressError(message: string): boolean { + const now = Date.now(); + + // Rate limit: max writes per second + if (now - _writeWindowStart > 1000) { + _writeCount = 0; + _writeWindowStart = now; + } + if (_writeCount >= MAX_WRITES_PER_SECOND) return true; + + // Dedup: suppress identical messages within window + const existing = _recentErrors.get(message); + if (existing && now - existing.firstSeen < DEDUP_WINDOW_MS) { + existing.count++; + return true; + } + + // Cleanup old entries + if (_recentErrors.size > 100) { + for (const [key, entry] of _recentErrors) { + if (now - entry.firstSeen > DEDUP_WINDOW_MS) _recentErrors.delete(key); + } + } + + _recentErrors.set(message, { count: 1, firstSeen: now }); + _writeCount++; + return false; +} + export function createLogger(component: string) { return { debug(message: string, meta?: Record<string, unknown>) { @@ -130,14 +166,21 @@ export function createLogger(component: string) { }, error(message: string, meta?: Record<string, unknown>) { if (currentLevel <= LOG_LEVELS.error) { + if (shouldSuppressError(message)) return; const entry = buildEntry("error", component, message, meta); - console.error(formatEntry("error", component, message, meta)); + // Use stderr.write to avoid Next.js console patching that triggers EPIPE loops + try { + process.stderr.write(formatEntry("error", component, message, meta) + "\n"); + } catch {} writeToFile(entry); } }, fatal(message: string, meta?: Record<string, unknown>) { + if (shouldSuppressError(message)) return; const entry = buildEntry("fatal", component, message, meta); - console.error(formatEntry("fatal", component, message, meta)); + try { + process.stderr.write(formatEntry("fatal", component, message, meta) + "\n"); + } catch {} writeToFile(entry); }, child(defaultMeta: Record<string, unknown>) { diff --git a/src/shared/validation/schemas.ts b/src/shared/validation/schemas.ts index 048a2615d9..4b9b129d67 100644 --- a/src/shared/validation/schemas.ts +++ b/src/shared/validation/schemas.ts @@ -1095,6 +1095,7 @@ export const validateProviderApiKeySchema = z.object({ apiKey: z.string().trim().min(1, "Provider and API key required"), validationModelId: z.string().trim().optional(), customUserAgent: z.string().trim().max(500).optional(), + baseUrl: z.string().trim().url().optional(), }); const geminiPartSchema = z diff --git a/tests/unit/auto-update-runtime.test.mjs b/tests/unit/auto-update-runtime.test.mjs index 2a8e1cdf2c..1ca8761a0f 100644 --- a/tests/unit/auto-update-runtime.test.mjs +++ b/tests/unit/auto-update-runtime.test.mjs @@ -36,6 +36,27 @@ describe("getAutoUpdateConfig", () => { }); describe("validateAutoUpdateRuntime", () => { + it("supports source mode when git is available in a git repository", async () => { + const config = autoUpdate.getAutoUpdateConfig({ + AUTO_UPDATE_MODE: "source", + }); + + const result = await autoUpdate.validateAutoUpdateRuntime( + config, + async (file) => { + if (file === "git") return { stdout: "git version 2.0.0", stderr: "" }; + throw new Error(`unexpected command: ${file}`); + }, + async () => true + ); + + assert.deepEqual(result, { + supported: true, + reason: null, + composeCommand: null, + }); + }); + it("reports missing docker socket for docker-compose mode", async () => { const config = autoUpdate.getAutoUpdateConfig({ AUTO_UPDATE_MODE: "docker-compose", @@ -102,3 +123,14 @@ describe("buildDockerComposeUpdateScript", () => { assert.match(script, /docker compose -f "\$COMPOSE_FILE" up -d --build "\$SERVICE"/); }); }); + +describe("buildSourceUpdateScript", () => { + it("includes git checkout, env sync, and rebuild steps", () => { + const script = autoUpdate.buildSourceUpdateScript("3.2.6", "upstream"); + + assert.match(script, /git fetch --tags 'upstream'/); + assert.match(script, /git checkout "v3\.2\.6"/); + assert.match(script, /node scripts\/sync-env\.mjs 2>\/dev\/null \|\| true/); + assert.match(script, /pm2 restart omniroute --update-env \|\| true/); + }); +}); diff --git a/tests/unit/auto-update.test.mjs b/tests/unit/auto-update.test.mjs index 1d1836bbc9..67cc2d79b0 100644 --- a/tests/unit/auto-update.test.mjs +++ b/tests/unit/auto-update.test.mjs @@ -54,19 +54,67 @@ test("detectComposeCommand prefers docker compose and falls back to docker-compo }); test("validateAutoUpdateRuntime covers source, docker preconditions and successful docker runtime", async () => { - const sourceValidation = await autoUpdate.validateAutoUpdateRuntime({ - mode: "source", - repoDir: "/repo", - composeFile: "/repo/docker-compose.yml", - composeProfile: "cli", - composeService: "omniroute-cli", - gitRemote: "origin", - patchCommits: [], - logPath: "/tmp/log", + const sourceValidation = await autoUpdate.validateAutoUpdateRuntime( + { + mode: "source", + repoDir: "/repo", + composeFile: "/repo/docker-compose.yml", + composeProfile: "cli", + composeService: "omniroute-cli", + gitRemote: "origin", + patchCommits: [], + logPath: "/tmp/log", + }, + async (command, args) => { + if (command === "git" && args[0] === "--version") { + return { stdout: "git version 2.0", stderr: "" }; + } + throw new Error(`unexpected: ${command}`); + }, + async () => true + ); + + assert.deepEqual(sourceValidation, { + supported: true, + reason: null, + composeCommand: null, }); - assert.equal(sourceValidation.supported, false); - assert.match(sourceValidation.reason, /Manual 'git pull && npm install && npm run build'/); + const sourceMissingGitRepo = await autoUpdate.validateAutoUpdateRuntime( + { + mode: "source", + repoDir: "/repo", + composeFile: "/repo/docker-compose.yml", + composeProfile: "cli", + composeService: "omniroute-cli", + gitRemote: "origin", + patchCommits: [], + logPath: "/tmp/log", + }, + async () => ({ stdout: "git version 2.0", stderr: "" }), + async () => false + ); + assert.equal(sourceMissingGitRepo.supported, false); + assert.match(sourceMissingGitRepo.reason, /Not a git repository/); + + const sourceMissingGit = await autoUpdate.validateAutoUpdateRuntime( + { + mode: "source", + repoDir: "/repo", + composeFile: "/repo/docker-compose.yml", + composeProfile: "cli", + composeService: "omniroute-cli", + gitRemote: "origin", + patchCommits: [], + logPath: "/tmp/log", + }, + async () => { + throw new Error("git missing"); + }, + async () => true + ); + assert.equal(sourceMissingGit.supported, false); + assert.match(sourceMissingGit.reason, /git is not available/); const missingRepo = await autoUpdate.validateAutoUpdateRuntime( { @@ -171,12 +219,44 @@ test("validateAutoUpdateRuntime covers source, docker preconditions and successf }); }); -test("auto update script builders generate npm and docker-compose scripts with quoting and patch commits", () => { +test("ensureGitTagExists verifies refs/tags paths and throws a clear error when missing", async () => { + const calls = []; + await autoUpdate.ensureGitTagExists("v3.6.0", async (command, args, options) => { + calls.push({ command, args, options }); + return { stdout: "deadbeef", stderr: "" }; + }); + + assert.deepEqual(calls, [ + { + command: "git", + args: ["rev-parse", "-q", "--verify", "refs/tags/v3.6.0"], + options: { + timeout: 10_000, + cwd: process.cwd(), + }, + }, + ]); + + await assert.rejects( + autoUpdate.ensureGitTagExists("v9.9.9", async () => { + throw new Error("missing tag"); + }), + /Git tag not found: v9\.9\.9/ + ); +}); + +test("auto update script builders generate npm, source, and docker-compose scripts with quoting and patch commits", () => { const npmScript = autoUpdate.buildNpmUpdateScript("3.6.0"); assert.match(npmScript, /npm install -g omniroute@3.6.0/); assert.match(npmScript, /pm2 restart omniroute \|\| true/); assert.match(npmScript, /Successfully updated to v3.6.0/); + const sourceScript = autoUpdate.buildSourceUpdateScript("3.6.0", "upstream"); + assert.match(sourceScript, /git fetch --tags 'upstream'/); + assert.match(sourceScript, /git stash --include-untracked/); + assert.match(sourceScript, /node scripts\/sync-env\.mjs 2>\/dev\/null \|\| true/); + assert.match(sourceScript, /Successfully updated to v3\.6\.0/); + const dockerScript = autoUpdate.buildDockerComposeUpdateScript({ latest: "3.6.0", composeCommand: "docker-compose", @@ -205,11 +285,45 @@ test("launchAutoUpdate returns validation failures and starts detached update sc AUTO_UPDATE_MODE: "source", AUTO_UPDATE_LOG_PATH: "/tmp/auto-update-source.log", }, + existsImpl: async () => false, }); assert.equal(unsupported.started, false); assert.equal(unsupported.channel, "source"); - assert.match(unsupported.error, /Manual 'git pull && npm install && npm run build'/); + assert.match(unsupported.error, /Not a git repository/); + + const sourceSpawnCalls = []; + const sourceStarted = await autoUpdate.launchAutoUpdate({ + latest: "3.6.0", + env: { + AUTO_UPDATE_MODE: "source", + AUTO_UPDATE_GIT_REMOTE: "upstream", + AUTO_UPDATE_LOG_PATH: "/tmp/auto-update-source.log", + }, + execFileImpl: async (command, args) => { + if (command === "git" && args[0] === "--version") { + return { stdout: "git version 2.0", stderr: "" }; + } + throw new Error(`unexpected exec: ${command}`); + }, + existsImpl: async () => true, + spawnImpl: (command, args, options) => { + sourceSpawnCalls.push({ command, args, options, unrefCalled: false }); + return { + unref() { + sourceSpawnCalls[0].unrefCalled = true; + }, + }; + }, + }); + + assert.equal(sourceStarted.started, true); + assert.equal(sourceStarted.channel, "source"); + assert.equal(sourceStarted.composeCommand, null); + assert.equal(sourceSpawnCalls.length, 1); + assert.match(sourceSpawnCalls[0].args[1], /git fetch --tags 'upstream'/); + assert.match(sourceSpawnCalls[0].args[1], /npm run build/); + assert.equal(sourceSpawnCalls[0].unrefCalled, true); const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-autoupdate-")); const repoDir = path.join(tempRoot, "repo"); diff --git a/tests/unit/claude-oauth-provider.test.mjs b/tests/unit/claude-oauth-provider.test.mjs index 6189f60664..c451391a24 100644 --- a/tests/unit/claude-oauth-provider.test.mjs +++ b/tests/unit/claude-oauth-provider.test.mjs @@ -1,8 +1,25 @@ import test from "node:test"; import assert from "node:assert/strict"; -import { claude } from "../../src/lib/oauth/providers/claude.ts"; -import { CLAUDE_CONFIG } from "../../src/lib/oauth/constants/oauth.ts"; +Object.assign(process.env, { + CLAUDE_OAUTH_CLIENT_ID: "9d1c250a-e61b-44d9-88ed-5944d1962f5e", + CODEX_OAUTH_CLIENT_ID: "app_EMoamEEZ73f0CkXaXp7hrann", + GEMINI_OAUTH_CLIENT_ID: + "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com", + GEMINI_OAUTH_CLIENT_SECRET: "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", + GEMINI_CLI_OAUTH_CLIENT_ID: + "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com", + GEMINI_CLI_OAUTH_CLIENT_SECRET: "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", + QWEN_OAUTH_CLIENT_ID: "f0304373b74a44d2b584a3fb70ca9e56", + KIMI_CODING_OAUTH_CLIENT_ID: "17e5f671-d194-4dfb-9706-5516cb48c098", + ANTIGRAVITY_OAUTH_CLIENT_ID: + "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com", + ANTIGRAVITY_OAUTH_CLIENT_SECRET: "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", + GITHUB_OAUTH_CLIENT_ID: "Iv1.b507a08c87ecfe98", +}); + +const { claude } = await import("../../src/lib/oauth/providers/claude.ts"); +const { CLAUDE_CONFIG } = await import("../../src/lib/oauth/constants/oauth.ts"); const originalFetch = globalThis.fetch; diff --git a/tests/unit/mask-email.test.mjs b/tests/unit/mask-email.test.mjs new file mode 100644 index 0000000000..64543544fd --- /dev/null +++ b/tests/unit/mask-email.test.mjs @@ -0,0 +1,51 @@ +import { describe, it } from "node:test"; +import assert from "node:assert/strict"; +import { maskEmail } from "../../src/shared/utils/maskEmail.ts"; + +describe("maskEmail", () => { + it("masks standard email correctly", () => { + assert.equal(maskEmail("diego.souza@gmail.com"), "di*********@g****.com"); + }); + + it("masks email with short username (exactly visibleChars)", () => { + // username "ab" has length 2 = visibleChars, so returns as-is + assert.equal(maskEmail("ab@gmail.com"), "ab@gmail.com"); + }); + + it("masks email with longer username", () => { + const result = maskEmail("hello@example.com"); + assert.equal(result, "he***@e******.com"); + }); + + it("returns empty string for null", () => { + assert.equal(maskEmail(null), ""); + }); + + it("returns empty string for undefined", () => { + assert.equal(maskEmail(undefined), ""); + }); + + it("returns empty string for empty string", () => { + assert.equal(maskEmail(""), ""); + }); + + it("returns original if no @ symbol", () => { + assert.equal(maskEmail("notanemail"), "notanemail"); + }); + + it("handles multi-part TLDs correctly", () => { + const result = maskEmail("user@company.co.uk"); + assert.ok(result.endsWith(".co.uk"), `Expected .co.uk suffix, got: ${result}`); + assert.ok(result.includes("@"), "Should contain @"); + }); + + it("handles single-char domain name", () => { + const result = maskEmail("user@x.com"); + assert.ok(result.includes("@x.com"), `Expected @x.com in: ${result}`); + }); + + it("allows customizing visibleChars", () => { + const result = maskEmail("hello@example.com", 3); + assert.ok(result.startsWith("hel"), `Expected to start with 'hel', got: ${result}`); + }); +}); diff --git a/tests/unit/oauth-providers-config.test.mjs b/tests/unit/oauth-providers-config.test.mjs index 5ecb33550a..b4a6d162ae 100644 --- a/tests/unit/oauth-providers-config.test.mjs +++ b/tests/unit/oauth-providers-config.test.mjs @@ -1,8 +1,30 @@ import test from "node:test"; import assert from "node:assert/strict"; -import PROVIDERS from "../../src/lib/oauth/providers/index.ts"; -import { +const originalEnv = { ...process.env }; +Object.assign(process.env, { + CLAUDE_OAUTH_CLIENT_ID: "9d1c250a-e61b-44d9-88ed-5944d1962f5e", + CODEX_OAUTH_CLIENT_ID: "app_EMoamEEZ73f0CkXaXp7hrann", + GEMINI_OAUTH_CLIENT_ID: + "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com", + GEMINI_OAUTH_CLIENT_SECRET: "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", + GEMINI_CLI_OAUTH_CLIENT_ID: + "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com", + GEMINI_CLI_OAUTH_CLIENT_SECRET: "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", + QWEN_OAUTH_CLIENT_ID: "f0304373b74a44d2b584a3fb70ca9e56", + KIMI_CODING_OAUTH_CLIENT_ID: "17e5f671-d194-4dfb-9706-5516cb48c098", + ANTIGRAVITY_OAUTH_CLIENT_ID: + "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com", + ANTIGRAVITY_OAUTH_CLIENT_SECRET: "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", + GITHUB_OAUTH_CLIENT_ID: "Iv1.b507a08c87ecfe98", +}); + +const providersModule = await import("../../src/lib/oauth/providers/index.ts"); +const oauthModule = await import("../../src/lib/oauth/constants/oauth.ts"); +const registryModule = await import("../../open-sse/config/providerRegistry.ts"); + +const PROVIDERS = providersModule.default; +const { ANTIGRAVITY_CONFIG, CLAUDE_CONFIG, CLINE_CONFIG, @@ -14,11 +36,11 @@ import { KIMI_CODING_CONFIG, KIRO_CONFIG, OAUTH_TIMEOUT, - PROVIDERS as OAUTH_PROVIDER_IDS, + PROVIDERS: OAUTH_PROVIDER_IDS, QODER_CONFIG, QWEN_CONFIG, -} from "../../src/lib/oauth/constants/oauth.ts"; -import { REGISTRY } from "../../open-sse/config/providerRegistry.ts"; +} = oauthModule; +const { REGISTRY } = registryModule; const originalFetch = globalThis.fetch; @@ -137,6 +159,16 @@ test.afterEach(() => { globalThis.fetch = originalFetch; }); +test.after(() => { + globalThis.fetch = originalFetch; + for (const key of Object.keys(process.env)) { + if (!(key in originalEnv)) { + delete process.env[key]; + } + } + Object.assign(process.env, originalEnv); +}); + test("OAuth provider registry exposes every expected provider exactly once", () => { assert.deepEqual(Object.keys(PROVIDERS), EXPECTED_PROVIDER_KEYS); assert.equal(new Set(Object.keys(PROVIDERS)).size, EXPECTED_PROVIDER_KEYS.length); @@ -279,7 +311,10 @@ test("provider-specific config shapes remain valid for special cases", () => { }); test("Gemini OAuth defaults do not hardcode a client secret fallback", () => { - assert.equal(GEMINI_CONFIG.clientSecret, process.env.GEMINI_OAUTH_CLIENT_SECRET || ""); + assert.equal( + GEMINI_CONFIG.clientSecret, + process.env.GEMINI_CLI_OAUTH_CLIENT_SECRET || process.env.GEMINI_OAUTH_CLIENT_SECRET || "" + ); assert.equal(REGISTRY.gemini.oauth.clientSecretDefault, ""); assert.equal(REGISTRY["gemini-cli"].oauth.clientSecretDefault, ""); }); diff --git a/tests/unit/openrouter-registry.test.mjs b/tests/unit/openrouter-registry.test.mjs new file mode 100644 index 0000000000..25ee0eaf76 --- /dev/null +++ b/tests/unit/openrouter-registry.test.mjs @@ -0,0 +1,83 @@ +import { describe, it } from "node:test"; +import assert from "node:assert/strict"; +import { + getEmbeddingProvider, + parseEmbeddingModel, + getAllEmbeddingModels, +} from "../../open-sse/config/embeddingRegistry.ts"; +import { + getImageProvider, + parseImageModel, +} from "../../open-sse/config/imageRegistry.ts"; + +describe("OpenRouter & GitHub registry entries (#960)", () => { + // ── Embedding Registry ────────────────────────────────────────────────── + + describe("embeddingRegistry — openrouter", () => { + it("resolves openrouter provider config", () => { + const p = getEmbeddingProvider("openrouter"); + assert.ok(p, "openrouter should be in EMBEDDING_PROVIDERS"); + assert.equal(p.baseUrl, "https://openrouter.ai/api/v1/embeddings"); + assert.equal(p.authHeader, "bearer"); + }); + + it("openrouter has at least 3 models", () => { + const p = getEmbeddingProvider("openrouter"); + assert.ok(p.models.length >= 3, `Expected ≥3 models, got ${p.models.length}`); + }); + + it("parses openrouter/openai/text-embedding-3-small correctly", () => { + const result = parseEmbeddingModel("openrouter/openai/text-embedding-3-small"); + assert.equal(result.provider, "openrouter"); + assert.equal(result.model, "openai/text-embedding-3-small"); + }); + + it("openrouter models appear in getAllEmbeddingModels", () => { + const all = getAllEmbeddingModels(); + const orModels = all.filter((m) => m.provider === "openrouter"); + assert.ok(orModels.length > 0, "Expected openrouter models in full list"); + }); + }); + + describe("embeddingRegistry — github", () => { + it("resolves github provider config", () => { + const p = getEmbeddingProvider("github"); + assert.ok(p, "github should be in EMBEDDING_PROVIDERS"); + assert.equal(p.baseUrl, "https://models.inference.ai.azure.com/embeddings"); + assert.equal(p.authHeader, "bearer"); + }); + + it("github has at least 2 models", () => { + const p = getEmbeddingProvider("github"); + assert.ok(p.models.length >= 2, `Expected ≥2 models, got ${p.models.length}`); + }); + + it("parses github/text-embedding-3-small correctly", () => { + const result = parseEmbeddingModel("github/text-embedding-3-small"); + assert.equal(result.provider, "github"); + assert.equal(result.model, "text-embedding-3-small"); + }); + }); + + // ── Image Registry ─────────────────────────────────────────────────────── + + describe("imageRegistry — openrouter", () => { + it("resolves openrouter image provider config", () => { + const p = getImageProvider("openrouter"); + assert.ok(p, "openrouter should be in IMAGE_PROVIDERS"); + assert.equal(p.baseUrl, "https://openrouter.ai/api/v1/images/generations"); + assert.equal(p.format, "openai"); + }); + + it("openrouter image provider has at least 2 models", () => { + const p = getImageProvider("openrouter"); + assert.ok(p.models.length >= 2, `Expected ≥2 models, got ${p.models.length}`); + }); + + it("parses openrouter/openai/dall-e-3 correctly", () => { + const result = parseImageModel("openrouter/openai/dall-e-3"); + assert.equal(result.provider, "openrouter"); + assert.equal(result.model, "openai/dall-e-3"); + }); + }); +}); diff --git a/tests/unit/qoder-cli.test.mjs b/tests/unit/qoder-cli.test.mjs index a494b6f0f2..6452acb913 100644 --- a/tests/unit/qoder-cli.test.mjs +++ b/tests/unit/qoder-cli.test.mjs @@ -242,48 +242,121 @@ test("qoder cli failure parsing classifies auth, timeout and generic upstream er test("validateQoderCliPat builds COSY headers and handles success, HTTP failures and fetch errors", async () => { const originalFetch = globalThis.fetch; - const calls = []; - globalThis.fetch = async (url, options = {}) => { - calls.push({ url: String(url), options }); - if (calls.length === 1) { + // Test 1: Success path (ping OK + validation OK) + { + let callIndex = 0; + globalThis.fetch = async (url, options = {}) => { + callIndex++; + const urlStr = String(url); + // Ping request + if (urlStr.includes("/ping")) { + return new Response("pong", { status: 200 }); + } + // Validation request return new Response("ok", { status: 200 }); - } - if (calls.length === 2) { - return new Response("denied", { status: 403 }); - } - throw new Error("network down"); - }; + }; - try { const success = await qoderCli.validateQoderCliPat({ apiKey: "pat-token", providerSpecificData: { validationModelId: "kimi-k2" }, }); + assert.equal(success.valid, true); + assert.equal(success.error, null); + assert.equal(success.unsupported, false); + } + + // Test 2: Auth failure (ping OK + validation 403) + { + globalThis.fetch = async (url) => { + if (String(url).includes("/ping")) { + return new Response("pong", { status: 200 }); + } + return new Response("denied", { status: 403 }); + }; + const denied = await qoderCli.validateQoderCliPat({ apiKey: "pat-token", providerSpecificData: { modelId: "qwen3-max" }, }); - const failed = await qoderCli.validateQoderCliPat({ apiKey: "pat-token" }); - - const firstBody = JSON.parse(String(calls[0].options.body)); - assert.equal(success.valid, true); - assert.equal(success.error, null); - assert.equal(success.unsupported, false); - assert.equal(calls[0].url.includes("agent_chat_generation"), true); - assert.equal(firstBody.model, "kimi-k2"); - assert.equal(firstBody.stream, false); - assert.match(calls[0].options.headers.Authorization, /^Bearer COSY\./); - assert.equal(typeof calls[0].options.headers["Cosy-Key"], "string"); - assert.equal(calls[0].options.signal instanceof AbortSignal, true); - assert.equal(denied.valid, false); - assert.match(denied.error, /HTTP 403: denied/); + assert.match(denied.error, /Authentication failed/); assert.equal(denied.unsupported, false); + } + // Test 3: Network error (ping fails) + { + globalThis.fetch = async () => { + throw new Error("network down"); + }; + + const failed = await qoderCli.validateQoderCliPat({ apiKey: "pat-token" }); assert.equal(failed.valid, false); - assert.equal(failed.error, "network down"); + assert.match(failed.error, /Cannot reach Qoder API/); assert.equal(failed.unsupported, false); + } + + // Test 4: Non-auth 4xx treated as auth-pass + { + globalThis.fetch = async (url) => { + if (String(url).includes("/ping")) { + return new Response("pong", { status: 200 }); + } + return new Response("bad request", { status: 400 }); + }; + + const badRequest = await qoderCli.validateQoderCliPat({ apiKey: "pat-token" }); + assert.equal(badRequest.valid, true); + assert.equal(badRequest.error, null); + } + + // Test 5: Empty token returns clear error + { + await withEnv({ QODER_PERSONAL_ACCESS_TOKEN: undefined }, async () => { + const noToken = await qoderCli.validateQoderCliPat({ apiKey: "" }); + assert.equal(noToken.valid, false); + assert.match(noToken.error, /No Qoder token provided/); + }); + } + + // Test 6: Encrypted blob token is rejected with guidance + { + const blobToken = "x".repeat(600); + const blobResult = await qoderCli.validateQoderCliPat({ apiKey: blobToken }); + assert.equal(blobResult.valid, false); + assert.match(blobResult.error, /encrypted auth blob/); + } + + globalThis.fetch = originalFetch; +}); + +test("validateQoderCliPat succeeds when the validation endpoint returns OK", async () => { + const originalFetch = globalThis.fetch; + globalThis.fetch = async (url) => { + if (String(url).includes("/ping")) return new Response("pong", { status: 200 }); + return new Response("ok", { status: 200 }); + }; + + try { + const result = await qoderCli.validateQoderCliPat({ apiKey: "valid-pat" }); + assert.equal(result.valid, true); + assert.equal(result.error, null); + } finally { + globalThis.fetch = originalFetch; + } +}); + +test("validateQoderCliPat returns HTTP failures without touching the network", async () => { + const originalFetch = globalThis.fetch; + globalThis.fetch = async (url) => { + if (String(url).includes("/ping")) return new Response("pong", { status: 200 }); + return new Response("server error", { status: 500 }); + }; + + try { + const result = await qoderCli.validateQoderCliPat({ apiKey: "valid-pat" }); + assert.equal(result.valid, false); + assert.match(result.error, /HTTP 500/); } finally { globalThis.fetch = originalFetch; } diff --git a/tests/unit/qoder-executor.test.mjs b/tests/unit/qoder-executor.test.mjs index 21a0d5dacf..9cbbeb73ba 100644 --- a/tests/unit/qoder-executor.test.mjs +++ b/tests/unit/qoder-executor.test.mjs @@ -110,10 +110,12 @@ test("parseQoderCliFailure classifies auth, upstream and timeout failures", () = test("validateQoderCliPat succeeds when the validation endpoint returns OK", async () => { const originalFetch = globalThis.fetch; globalThis.fetch = async (url, options) => { - assert.match( - String(url), - /api1\.qoder\.sh\/algo\/api\/v2\/service\/pro\/sse\/agent_chat_generation/ - ); + const urlStr = String(url); + // Handle ping check + if (urlStr.includes("/ping")) { + return new Response("pong", { status: 200 }); + } + assert.match(urlStr, /api1\.qoder\.sh\/algo\/api\/v2\/service\/pro\/sse\/agent_chat_generation/); assert.equal(options.method, "POST"); assert.match(String(options.headers.Authorization), /^Bearer COSY\./); return new Response("{}", { status: 200 }); @@ -127,17 +129,18 @@ test("validateQoderCliPat succeeds when the validation endpoint returns OK", asy } }); -test("validateQoderCliPat returns HTTP failures without touching the network", async () => { +test("validateQoderCliPat returns auth failures with actionable error", async () => { const originalFetch = globalThis.fetch; - globalThis.fetch = async () => new Response("Invalid API key", { status: 401 }); + globalThis.fetch = async (url) => { + if (String(url).includes("/ping")) return new Response("pong", { status: 200 }); + return new Response("Invalid API key", { status: 401 }); + }; try { const result = await validateQoderCliPat({ apiKey: "pat_bad" }); - assert.deepEqual(result, { - valid: false, - error: "HTTP 401: Invalid API key", - unsupported: false, - }); + assert.equal(result.valid, false); + assert.match(result.error, /Authentication failed/); + assert.equal(result.unsupported, false); } finally { globalThis.fetch = originalFetch; } diff --git a/tests/unit/qoder-oauth-config.test.mjs b/tests/unit/qoder-oauth-config.test.mjs index c5e6c9251d..66ae23a2ae 100644 --- a/tests/unit/qoder-oauth-config.test.mjs +++ b/tests/unit/qoder-oauth-config.test.mjs @@ -1,9 +1,26 @@ import test from "node:test"; import assert from "node:assert/strict"; -import { OAUTH_ENDPOINTS } from "../../open-sse/config/constants.ts"; -import { qoder } from "../../src/lib/oauth/providers/qoder.ts"; -import { QODER_CONFIG } from "../../src/lib/oauth/constants/oauth.ts"; +Object.assign(process.env, { + CLAUDE_OAUTH_CLIENT_ID: "9d1c250a-e61b-44d9-88ed-5944d1962f5e", + CODEX_OAUTH_CLIENT_ID: "app_EMoamEEZ73f0CkXaXp7hrann", + GEMINI_OAUTH_CLIENT_ID: + "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com", + GEMINI_OAUTH_CLIENT_SECRET: "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", + GEMINI_CLI_OAUTH_CLIENT_ID: + "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com", + GEMINI_CLI_OAUTH_CLIENT_SECRET: "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", + QWEN_OAUTH_CLIENT_ID: "f0304373b74a44d2b584a3fb70ca9e56", + KIMI_CODING_OAUTH_CLIENT_ID: "17e5f671-d194-4dfb-9706-5516cb48c098", + ANTIGRAVITY_OAUTH_CLIENT_ID: + "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com", + ANTIGRAVITY_OAUTH_CLIENT_SECRET: "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", + GITHUB_OAUTH_CLIENT_ID: "Iv1.b507a08c87ecfe98", +}); + +const { OAUTH_ENDPOINTS } = await import("../../open-sse/config/constants.ts"); +const { qoder } = await import("../../src/lib/oauth/providers/qoder.ts"); +const { QODER_CONFIG } = await import("../../src/lib/oauth/constants/oauth.ts"); test("Qoder OAuth defaults no longer point to qoder.cn", () => { assert.doesNotMatch(QODER_CONFIG.authorizeUrl || "", /qoder\.cn/i); diff --git a/tests/unit/resolve-omniroute-base-url.test.mjs b/tests/unit/resolve-omniroute-base-url.test.mjs new file mode 100644 index 0000000000..3e629fe1e6 --- /dev/null +++ b/tests/unit/resolve-omniroute-base-url.test.mjs @@ -0,0 +1,52 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { + DEFAULT_OMNIROUTE_BASE_URL, + resolveOmniRouteBaseUrl, +} from "../../src/shared/utils/resolveOmniRouteBaseUrl.ts"; + +test("resolveOmniRouteBaseUrl prefers OMNIROUTE_BASE_URL", () => { + assert.equal( + resolveOmniRouteBaseUrl({ + OMNIROUTE_BASE_URL: "https://internal.example.com/", + BASE_URL: "https://base.example.com", + NEXT_PUBLIC_BASE_URL: "https://public.example.com", + }), + "https://internal.example.com" + ); +}); + +test("resolveOmniRouteBaseUrl falls back to BASE_URL", () => { + assert.equal( + resolveOmniRouteBaseUrl({ + BASE_URL: "https://base.example.com/", + NEXT_PUBLIC_BASE_URL: "https://public.example.com", + }), + "https://base.example.com" + ); +}); + +test("resolveOmniRouteBaseUrl falls back to NEXT_PUBLIC_BASE_URL", () => { + assert.equal( + resolveOmniRouteBaseUrl({ + NEXT_PUBLIC_BASE_URL: "https://public.example.com/", + }), + "https://public.example.com" + ); +}); + +test("resolveOmniRouteBaseUrl ignores blank values", () => { + assert.equal( + resolveOmniRouteBaseUrl({ + OMNIROUTE_BASE_URL: " ", + BASE_URL: "", + NEXT_PUBLIC_BASE_URL: " https://public.example.com/ ", + }), + "https://public.example.com" + ); +}); + +test("resolveOmniRouteBaseUrl uses the default localhost fallback", () => { + assert.equal(resolveOmniRouteBaseUrl({}), DEFAULT_OMNIROUTE_BASE_URL); +}); diff --git a/tests/unit/sync-env.test.mjs b/tests/unit/sync-env.test.mjs new file mode 100644 index 0000000000..7720b15a6e --- /dev/null +++ b/tests/unit/sync-env.test.mjs @@ -0,0 +1,99 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +const { syncEnv } = await import("../../scripts/sync-env.mjs"); + +function createTempRoot() { + return fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-sync-env-")); +} + +function writeEnvExample(rootDir) { + fs.writeFileSync( + path.join(rootDir, ".env.example"), + [ + "JWT_SECRET=", + "API_KEY_SECRET=", + "STORAGE_ENCRYPTION_KEY=", + "MACHINE_ID_SALT=", + "CLAUDE_OAUTH_CLIENT_ID=claude-default", + "CODEX_OAUTH_CLIENT_ID=codex-default", + "# COMMENTED_KEY=skip-me", + "", + ].join("\n"), + "utf8" + ); +} + +test("syncEnv creates .env from .env.example and generates blank secrets", () => { + const rootDir = createTempRoot(); + + try { + writeEnvExample(rootDir); + + const result = syncEnv({ rootDir, quiet: true }); + const envContent = fs.readFileSync(path.join(rootDir, ".env"), "utf8"); + + assert.deepEqual(result, { created: true, added: 6 }); + assert.match(envContent, /^JWT_SECRET=.{32,}$/m); + assert.match(envContent, /^API_KEY_SECRET=.{32,}$/m); + assert.match(envContent, /^STORAGE_ENCRYPTION_KEY=.{32,}$/m); + assert.match(envContent, /^MACHINE_ID_SALT=omniroute-/m); + assert.match(envContent, /^CLAUDE_OAUTH_CLIENT_ID=claude-default$/m); + assert.match(envContent, /^CODEX_OAUTH_CLIENT_ID=codex-default$/m); + assert.doesNotMatch(envContent, /^COMMENTED_KEY=/m); + } finally { + fs.rmSync(rootDir, { recursive: true, force: true }); + } +}); + +test("syncEnv appends only missing keys and preserves existing values", () => { + const rootDir = createTempRoot(); + + try { + writeEnvExample(rootDir); + fs.writeFileSync( + path.join(rootDir, ".env"), + [ + "JWT_SECRET=my-custom-secret-that-should-stay", + "CLAUDE_OAUTH_CLIENT_ID=custom-claude", + "", + ].join("\n"), + "utf8" + ); + + const result = syncEnv({ rootDir, quiet: true }); + const envContent = fs.readFileSync(path.join(rootDir, ".env"), "utf8"); + + assert.deepEqual(result, { created: false, added: 4 }); + assert.match(envContent, /^JWT_SECRET=my-custom-secret-that-should-stay$/m); + assert.match(envContent, /^CLAUDE_OAUTH_CLIENT_ID=custom-claude$/m); + assert.match(envContent, /^API_KEY_SECRET=.{32,}$/m); + assert.match(envContent, /^STORAGE_ENCRYPTION_KEY=.{32,}$/m); + assert.match(envContent, /^MACHINE_ID_SALT=omniroute-/m); + assert.match(envContent, /^CODEX_OAUTH_CLIENT_ID=codex-default$/m); + assert.match(envContent, /Auto-added by sync-env/); + } finally { + fs.rmSync(rootDir, { recursive: true, force: true }); + } +}); + +test("syncEnv is idempotent when .env is already complete", () => { + const rootDir = createTempRoot(); + + try { + writeEnvExample(rootDir); + syncEnv({ rootDir, quiet: true }); + + const before = fs.readFileSync(path.join(rootDir, ".env"), "utf8"); + const result = syncEnv({ rootDir, quiet: true }); + const after = fs.readFileSync(path.join(rootDir, ".env"), "utf8"); + + assert.deepEqual(result, { created: false, added: 0 }); + assert.equal(after, before); + } finally { + fs.rmSync(rootDir, { recursive: true, force: true }); + } +});