Compare commits

..

79 Commits

Author SHA1 Message Date
Xiangzhe
30cac12f5e fix(build): stop bundling the better-sqlite3 stub at runtime (#11343)
next.config.mjs aliased `better-sqlite3` to its build-time stub
unconditionally, recording the premise that "runtime still uses the real
package via serverExternalPackages". That premise does not hold: a
Turbopack resolveAlias rewrites the request BEFORE the externals check
runs, so the request stopped matching the serverExternalPackages entry
and the stub was baked into the shipped bundle.

Every artifact built from the release tip then answered HTTP 500 on
every route -- the sync driver failed with "r(...) is not a constructor"
(the minified stub export), fell through node:sqlite and sql.js, and the
instrumentation hook aborted at boot.

Same failure shape as #6344, one alias above it in the same object, so
it gets the same treatment: a shared flag helper makes the alias opt-in
via OMNIROUTE_BETTER_SQLITE3_STUB=1, and a default build externalizes
the real native addon. Nobody sets the flag today; it exists for a build
host that genuinely hits the SIGABRT worker teardown from #10060, and
such a build is not shippable -- which the helper and the stub header
now say explicitly instead of describing the stub as a harmless
build-only stand-in.

Closes #11343
2026-08-24 09:56:20 -03:00
Diego Rodrigues de Sa e Souza
dafb4ae808 fix(deps): keep unused pnpm peers out of production (#11342)
* fix(deps): keep unused pnpm peers out of production

* docs(changelog): link dependency policy fix to PR 11342
2026-08-24 02:26:02 -03:00
Erick Kinnee
338c05dc6a fix(models): expose Ollama Cloud native effort tiers (#11307)
Validated on a 17-PR combined board: models-catalog-combo-metadata + ollama-cloud-reasoning-effort-tiers-10788 within the board's 287/287, typecheck:core clean, check:open-sse-typecheck clean, vitest 405/405. Publishes Ollama Cloud's native none/low/medium/high/max effort vocabulary for reasoning-capable passthrough/tagged models with no exact registry declaration, adds none to DeepSeek V4/GLM 5.x, and preserves narrower exact-model vocabularies (GPT-OSS) via intersection. Refs #10788. Thank you @ekinnee!
2026-08-24 01:55:47 -03:00
Nguyen Thanh Dat
6945bbaaba fix(db): escape regex metacharacters in group model patterns (#11311)
Validated on a 17-PR combined board: group-model-pattern-regex-escape within the board's 287/287, typecheck:core clean. matchesModelPattern() only substituted * before compiling to RegExp — every other metacharacter kept its regex meaning, so a malformed group pattern (unbalanced parens/brackets) threw uncaught and broke EVERY request for keys in that group, not just the malformed rule (isModelAllowedForKey has no try/catch and runs on the chat completion path and the /v1/models catalog). Thank you @ntdat812!
2026-08-24 01:55:42 -03:00
Ravi Tharuma
690f684bfc feat(audio): add native ElevenLabs HTTP compatibility routes (#11312)
Validated on a 17-PR combined board: elevenlabs-native-routes + hard-session-lease-bypass-inventory (9/9) within the board's 287/287, typecheck:core clean. Native ElevenLabs compatibility routes (voices, TTS, STT) reusing the stored credential via quota-preflight, sent only as xi-api-key; client authorization headers never forwarded. Closes #10556. Thank you @RaviTharuma!
2026-08-24 01:55:36 -03:00
Ravi Tharuma
c3cd1f94c0 feat(services): expose sanitized CLIProxyAPI account health (#11314)
Validated on a 17-PR combined board: cliproxy-accounts + cliproxy-tab + cliproxy-account-health + cliproxy-resolve-spawn-args-6877 (16/16) within the board's 287/287, typecheck:core clean, env-doc-sync clean. Exposes a sanitized read-only CLIProxyAPI account health view (5s-bounded client, explicit allowlist excluding names/paths/emails/tokens/status messages) through a management-authenticated API + dashboard card. Closes #6342. Thank you @RaviTharuma!
2026-08-24 01:55:31 -03:00
Webman
c21460f22a fix(lint): drain release-green hard failures on release/v3.8.50 (#9985) (#11317)
Validated on the resolved merge against the current release tip: pack-artifact-policy + cli-mcp-call-commands + cli-resilience-commands + cli-skills-commands + model-hide-multikey-11300 39/39, typecheck:core clean, eslint clean. Resolved a pt-BR.json wording conflict against #11322 (kept the tip's wording, semantically identical). Drains the real lint-fallout from the wave that was blocking the release-green verdict — dead code + newly-enforced React-Compiler hook rules. Thank you @jonlwheat2-gif!
2026-08-24 01:54:31 -03:00
Ravi Tharuma
9b14896a6c feat(api): add Google AI Studio Gemini TTS (#11315)
Validated on a 17-PR combined board: gemini-tts + vertex-media + audio-speech-handler (41/41) within the board's 287/287, typecheck:core clean. Registers public google/gemini-*-tts speech models and translates OpenAI-compatible /v1/audio/speech to the AI Studio generateContent audio contract, reusing the Vertex inline-audio/PCM/WAV conversion path. Batch TTS only, Gemini Live is out of scope. Thank you @RaviTharuma!
2026-08-24 01:50:44 -03:00
Ravi Tharuma
29f26293c3 feat(compression): isolate sync engines in bounded worker pool (#11318)
Validated on a 17-PR combined board: compression-worker + colocate-standalone-esm-scope within the board's 287/287, typecheck:core clean, env-doc-sync clean. Offloads eligible sync compression engines into a bounded worker_threads pool with a strict serializable DTO boundary and fail-open on spawn/worker/timeout failure. Closes #11023. Thank you @RaviTharuma!
2026-08-24 01:50:39 -03:00
Nguyen Thanh Dat
cb11592441 fix(db): judge the proxy URL host by address, not by spelling (#11319)
Validated on a 17-PR combined board: upstream-proxy-host-spelling 8/8 within the board's 287/287, typecheck:core clean. Routes src/lib/db/upstreamProxy.ts through the shared outbound-guard helpers instead of a private dotted-quad regex copy that had drifted since #10843 — closes the IPv4-mapped IPv6, ULA, link-local and CGNAT bypasses while preserving the deliberate loopback allow (CLIProxyAPI on localhost:8317). Multicast widened from /224\. to the full 224.0.0.0/4, called out explicitly. Thank you @ntdat812!
2026-08-24 01:50:35 -03:00
Ravi Tharuma
5ee646e68e fix(github): verify access tokens during health checks (#11320)
Validated on a 17-PR combined board: token-health-check + token-health-no-refresh-token-expired-5326 + token-refresh-service within the board's 287/287, typecheck:core clean. GitHub access-token-only connections are now actively verified on each due health interval (via the existing Copilot token exchange); the parent credential is marked expired only on a confirmed 401, never on 403/429/5xx/network failures; response bodies and transport messages no longer enter token-refresh logs. Closes #10352. Thank you @RaviTharuma!
2026-08-24 01:50:30 -03:00
Paco Cartones
6984676d95 fix(quality): report the real failure line and stop double-counting ci.yml gates (#11321)
Validated on a 17-PR combined board: validate-release-green within the board's 287/287, typecheck:core clean. Two accuracy bugs in the release-green verdict tool: an unanchored regex blamed a passing test line (matching a filename containing 'fail'), and 6 gates were double-recorded as both hard-failure and drift due to an id-format mismatch (ci.yml script name vs curated id). Found while reading the #9985 verdict — good catch.
2026-08-24 01:50:26 -03:00
Paco Cartones
79f8ae9d1e fix(i18n): add the 3 pt-BR CLI keys that break the locale parity test (#11322)
Validated on a 17-PR combined board: typecheck:core clean, gates within baseline. Restores 3 missing pt-BR CLI keys (setup.opencode, serve.tls_cert, serve.tls_key) — parity restored, 823/823. Thank you @pacocartones!
2026-08-24 01:49:52 -03:00
Nguyen Thanh Dat
04b2c47940 fix(i18n): restore three placeholders dropped from the pt catalogue (#11325)
Validated on a 17-PR combined board: i18n-placeholder-parity within the board's 287/287, typecheck:core clean. Restores 3 dropped placeholders in pt.json (the visible one: the cache tile's subtitle was repeating its own label instead of showing the total) and adds a 42-locale placeholder-set gate so this class of drift can't recur silently. Thank you @ntdat812!
2026-08-24 01:49:48 -03:00
Paco Cartones
24ac71465e test(db): make singleton reset survive the full suite and un-skip the 3 DB-state tests (#11327)
Validated on a 17-PR combined board: capture-critical-db-state 7/7 (all three previously-skipped tests now run) within the board's 287/287, typecheck:core clean. Fixes the racy DATA_DIR-after-dynamic-import isolation and removes a duplicate type declaration. Thank you @pacocartones!
2026-08-24 01:49:42 -03:00
Nguyen Thanh Dat
8d6f91b558 fix(security): refuse proxy-authorization and proxy-authenticate upstream (#11328)
Validated on a 17-PR combined board: upstream-headers-proxy-auth within the board's 287/287, typecheck:core clean, gates within baseline. proxy-authorization and proxy-authenticate join the FORBIDDEN denylist — forwarding proxy-authorization to a model provider would hand that provider the operator's own proxy credential. Thank you @ntdat812!
2026-08-24 01:49:37 -03:00
Diego Rodrigues de Sa e Souza
c3698eedcb fix(dashboard): route the Adapta tutorial CTA through the branded shortener (#11329)
Validated on a 17-PR combined board: TSX parses clean, eslint clean. Adapta tutorial CTA href now points at the branded shortener (link.omniroute.online/adapta) while keeping the visible link text as the real domain. Completes #11196's shortener rollout.
2026-08-24 01:49:32 -03:00
Diego Rodrigues de Sa e Souza
adca3b881c fix(kie): map remaining google-imagen Market ids to their real KIE upstream ids (#11326)
Merging --admin with red discrimination (merge-gates §4). Fails: ESLint warnings ratchet drift (inherited base-red), Unit Tests shards containing stream-timing.test.ts (CPU-contention timing flake, assert.ok(total >= 15)ms — unrelated to this PR's scope, open-sse/handlers/imageGeneration.ts), and dast-smoke (advisory, isRequired:null).
2026-08-24 01:10:23 -03:00
Diego Rodrigues de Sa e Souza
ac02c5b42f fix(resilience): don't clear an active rate-limit cooldown for non-quota_exhausted errors (#11277) (#11310)
Merging --admin: only fails are ESLint warnings ratchet drift (inherited base-red) and dast-smoke (advisory, isRequired:null). Zero overlap with this PR's scope (src/lib/usage/providerLimits.ts).
2026-08-23 22:55:33 -03:00
Diego Rodrigues de Sa e Souza
07d1816a45 fix(providers): hidden models leak into GET /v1/models (#11300) (#11309)
Merging --admin: only fails are ESLint warnings ratchet drift (inherited) and dast-smoke (advisory, isRequired:null). Zero overlap with this PR's file scope (src/app/api/v1/models/catalog.ts).
2026-08-23 22:35:29 -03:00
Diego Rodrigues de Sa e Souza
3192eb88d5 fix(providers): unify learned and declared reasoning-effort clamps on nearest-tier semantics (#11295) (#11305)
Merging --admin with red discrimination (merge-gates §4). 5/6 failing tests are the compression/i18n-vi/kiro/memory mini-cluster fixed by #11306 (this branch predates it). The 6th (token-health-check-kimi, 'jittered expiration window') is a timing-sensitive test — reproduces GREEN locally, name itself indicates randomized jitter, not a deterministic regression from this PR's reasoning-effort clamp change (zero file overlap). ESLint warnings + dast-smoke (advisory, isRequired:null) also inherited.
2026-08-23 22:17:12 -03:00
Diego Rodrigues de Sa e Souza
8969526437 fix(tests): drain compression/kiro/memory/i18n base-red mini-cluster (2026-08-24) (#11306)
Merging --admin: this is itself the base-red drain PR (compression/i18n-vi/i18n-pt-br/kiro/memory mini-cluster). Remaining fails (ESLint warnings ratchet drift, dast-smoke advisory) are not blocking; isRequired:null on dast-smoke.
2026-08-23 22:17:09 -03:00
Diego Rodrigues de Sa e Souza
5518916725 fix(chat): detect severity-classifier format in claudeClassifierCompat short-circuit (#11289) (#11304)
Validated on a 4-PR combined board: claude-classifier-compat 15/15 + 8189-classifier-compat-auto-narrow 5/5 sibling sweep, typecheck:core clean, gates within baseline. Detects the newer Claude Code severity-classifier request shape (stop_sequences carrying </severity>) and replies with <severity>0</severity> instead of the legacy <block>no</block> — the mismatch was failing both classifier stages closed and blocking gated tool calls (Bash, WebSearch). Closes #11289.
2026-08-23 21:34:54 -03:00
Diego Rodrigues de Sa e Souza
3daa455e1f fix(memory): avoid rejected mid-conversation system injection on Claude when preceding turn isn't a tool result (#11290) (#11303)
Validated on a 4-PR combined board: memory-cache-safe-injection + memory-glm-injection + chatcore-memory-skills-injection 39/39 (node:test), injection.test.ts 23/23 (vitest), typecheck:core clean, check:cycles clean, gates within baseline. Narrows the #3890 mid-array system-splice skip to the exact shape that 400s on Claude Opus 5 (splice point not preceded by a server tool result) instead of disabling the cache-safe optimization for every Claude request — preserves the fast path everywhere it's actually safe. Closes #11290.
2026-08-23 21:34:50 -03:00
Diego Rodrigues de Sa e Souza
d282ec7ad6 fix(providers): don't silently enable rate-limit protection on PATCH unless persisted (#11278) (#11302)
Validated on a 4-PR combined board: provider-patch-ratelimit-protection-11278 2/2 + 56/56 sibling suites, typecheck:core clean, gates within baseline. PUT /api/providers/[id] can no longer silently enable rate-limit protection just because EditConnectionModal sends rateLimitOverrides on every save — the runtime toggle now strictly follows the persisted DB row. Closes #11278.
2026-08-23 21:34:46 -03:00
Diego Rodrigues de Sa e Souza
1e81e521c0 fix(opencode-plugin): track active release branch in CI + align combo-id fixture (#11301)
Validated on a 4-PR combined board: @omniroute/opencode-plugin provider.test.ts 13/13, full plugin suite 343/343, YAML validated, typecheck:core clean, gates within baseline. CI branch trigger was pinned to release/v3.8.2 since creation (never fired mid-cycle) — now tracks [main, release/**] matching every other workflow's pattern; combo-id fixture aligned to the real #10821 unprefixed-lookup contract (RED 11/13 → GREEN 13/13).
2026-08-23 21:34:42 -03:00
Óscar Fonseca
a3c3117254 fix(translator): preserve omitted subagent session IDs (#11297)
Validated on a 3-PR combined board: openai-responses-opencode-subagent-sessionid within the board's 20/20, typecheck:core + check:open-sse-typecheck clean, gates within baseline. Uses null as the omission sentinel for OpenCode's optional default-less subagent.sessionID under Responses/Codex strict mode (which required every declared property) — models can now omit the field to spawn a new child instead of inventing filler IDs; the null is stripped before OpenCode sees the call, real child IDs pass through unchanged. Thank you @ofonseca-pyming!
2026-08-23 21:03:16 -03:00
Ravi Tharuma
d9a883ec53 docs(openapi): declare spec endpoint management auth (#11299)
Validated on a 3-PR combined board: openapi-security-tiers 1/1 within the board's 20/20, typecheck:core clean, gates within baseline. Declares GET /api/openapi/spec's real ManagementSessionAuth contract (conditional on requireLogin) — no runtime behavior change, just the doc catching up. Closes #10851. Thank you @RaviTharuma!
2026-08-23 21:03:11 -03:00
Ravi Tharuma
7913447bf0 docs(db): align cache guide with runtime settings (#11018) (#11294)
Validated on a 3-PR combined board: 11018-database-cache-docs 1/1 within the board's 20/20 focused suite, typecheck:core clean, gates within baseline. DATABASE_GUIDE.md now cites the real 64 MiB runtime default and the 1..1,000,000 KiB range, locked with a regression test. Thank you @RaviTharuma!
2026-08-23 21:03:07 -03:00
Diego Rodrigues de Sa e Souza
67fba53190 fix(tests): drain base-red cluster from 2026-08-23 merges (#9985) (#11280)
Validated on a 2-PR combined board: 158/158 across the drain's 17 focused test files (incl. integration qdrant-routes), typecheck:core + dashboard-typecheck clean, env-doc-sync, mutation-test-coverage, cli-i18n, file-size, changelog-integrity all green. Every red discriminated per-item as stale-test (contract intentionally moved, citing the origin PR) or real bug (fixed, never masked) across 3 base-advance waves (#9985): stryker registration, i18n gaps (health.* namespace mismatch + pt-BR parity), combo-token-window pins (872K), CLI catalog counts (prime-agent), the isComboStep single-target reasoning-transport-fallback regression, container-guard hermeticity, and 26 unsuppressed ESLint errors from the wave (typed qdrant adapter, import trim, justified disable with precedent). Drains the accumulated base-red cluster.
2026-08-23 20:32:46 -03:00
Diego Rodrigues de Sa e Souza
9cb91dee74 fix(security): close round-3 advisories (v7g9, x7vm, j7j4, jcm5) + exposure warning (wmgv) (#11261)
Validated on a 2-PR combined board: routeGuard 36/36 (within the 68/68 focused-file total), a2a-task-owner-idor 7/7, a2a-tasks-auth, search-baseurl-ssrf-guard, cli-serve-hostname, spawn-capable-prefixes-client-safe all green, typecheck:core + dashboard-typecheck clean, gates within baseline. Five real High-severity advisories fixed with TDD (each failing-then-passing): settings export/import-json ALWAYS_PROTECTED completion, MITM route LOCAL_ONLY+SPAWN_CAPABLE gating, search baseUrl SSRF/IMDS guard, A2A REST task auth+ownership (previously none at all), and the loud boot exposure warning. GHSA-cjv9 confirmed already closed on this base (verified). Round 3 of the advisory sweep.
2026-08-23 20:32:42 -03:00
ignamiranda
92f58603f9 Beginner UX: purpose-first Traffic Inspector header (#11283)
Validated on a 3-PR combined board: traffic-inspector-beginner-header suite green within the board's 30/30, typecheck:core + dashboard-typecheck clean, gates within baseline. Purpose-first orientation header for Traffic Inspector, existing inspection UI untouched. Thank you @ignamiranda!
2026-08-23 19:08:27 -03:00
ignamiranda
7cec8e32fd Beginner UX: Essentials sidebar preset (#11286)
Validated on a 3-PR combined board: sidebar-customization + sidebar-essentials-static 30/30 combined (across the board's 4 focused files), typecheck:core + dashboard-typecheck clean, gates within baseline. New Essentials sidebar preset gives first-time users a short beginner path while advanced tools stay reachable via Command Palette search. Thank you @ignamiranda!
2026-08-23 19:08:23 -03:00
engenhariaandrereis01-ai
d137368fb5 fix(oauth): stop overwriting Kiro connections that share a profile ARN (#10815) (#11287)
Validated on a 3-PR combined board: kiro-connection-identity 8/8 (written failing-first — 3 new cases red on the pristine release/v3.8.50 tip, green with this change), typecheck:core + dashboard-typecheck clean, all static gates within baseline. Root cause is exactly right: a CodeWhisperer profile ARN identifies the profile, not the account, and distinct Builder ID accounts via social login can share one — the ARN is now trusted only alongside a non-contradicting account-level identifier (email/clientId). Closes #10815. Thank you @engenhariaandrereis01-ai!
2026-08-23 19:08:18 -03:00
Diego Rodrigues de Sa e Souza
2904cf849d fix(security): clear new CodeQL code-scanning alerts (round 4) (#11293)
- open-sse/executors/github.ts: replace the Math.random() fallback in
  the Copilot correlation-id generators (x-request-id,
  x-interaction-id, x-client-session-id, x-agent-task-id) with a
  CSPRNG-backed randomIdFallback() (node:crypto randomBytes) — closes
  js/insecure-randomness with no behavior change (crypto.randomUUID
  stays the primary path).
- tests/unit/cli/_helpers/shellArgs.mjs: collapse the two sequential
  global .replace() unescape passes into a single left-to-right regex
  replace with alternation — closes js/double-escaping. The prior
  two-pass form let the first pass's output feed the second, which is
  exactly the double-(un)escaping bug pattern the query flags (e.g. an
  escaped-backslash-then-quote sequence could be misread depending on
  pass order).

Co-authored-by: Markus Hartung <mail@hartmark.se>
2026-08-23 19:06:53 -03:00
Markus Hartung
6158c9aeec fix: drop stray conflict leftover in managedModelImport (#11259 cherry-pick integration) 2026-08-23 18:14:06 -03:00
backryun
2764812ee4 fix(providers): eliminate Gemini 3.5 Flash 2026-08-23 18:13:11 -03:00
Marcel Wysocki
29caad9f3d feat(sse): discover Anthropic partner models on Vertex AI (#11279)
Validated on the combined 8-PR board + the branch itself: vertex-anthropic-models 4/4 (new — pushed to your branch as a fix-in-place commit per Hard Rule #8, covering the parser's global/project-scoped resource names, malformed-input handling, and the claude-* → targetFormat heuristic on vertex/vertex-partner), 88/88 across the board's focused suites, typecheck:core clean, gates within baseline. Anthropic partner models on Vertex AI now discover dynamically via the Model Garden publisher endpoint and route through the Claude translator even for models outside the static registry. Thank you @maci0!
2026-08-23 18:12:37 -03:00
Jack Smith
14d70a755b fix: resolve CLI mcp call protocol issues (BUG-001) (#10960)
Validated on the combined 8-PR board: all seven CLI command suites green (combo-suggest, compression, mcp-call, oneproxy, resilience, skills + the shared mcpStreamMock helper) within the board's 88/88, typecheck:core clean, gates within baseline. The CLI mcp call protocol fixes (BUG-001) land with full regression coverage across the affected commands. Thank you @YunyunZhai — and thank you for your patience while this one waited for review.
2026-08-23 18:11:50 -03:00
ignamiranda
3abbb60ec6 Beginner UX: soft first-run readiness card on Home (#11282)
Validated on the combined 8-PR board: home-page-static 4/4, check:dashboard-typecheck clean (220 pre-existing, all within frozen baseline — zero syntax errors), 88/88 across the board's focused suites, static gates within baseline. The soft first-run readiness card replaces the hard Home→onboarding redirect with a dismissable 4-step path. Thank you @ignamiranda!
2026-08-23 18:11:46 -03:00
Praveen K Palaniswamy
6d4c4843e9 fix(ollama): route models by advertised capability (#11087) — port of #11088 to the release line (#11271)
Validated on the combined 8-PR board: ollama-local-capabilities-routing 3/3, managed-model-import 9/9 (including the integration with the carried Gemini-3.5-Flash cleanup from #11259), 88/88 across the board's focused suites, typecheck:core + dashboard-typecheck clean, gates within baseline. This brings #11088 to the release line — it had squash-merged to main by base error (mine) — AND fixes the two defects the port caught: the global filter drop that leaked image/video models into OpenAI chat selections (now scoped to self-hosted providers) and the unregistered hard-lease credential site. Exemplary port discipline: byte-identical carry + the corrections in a separate reviewable commit + the superpowers docs deliberately left out. main still needs the same two-line fix. Thank you @yourspraveen!
2026-08-23 18:11:21 -03:00
Mina_
12986c44c9 fix(live-ws, dashboard): allow 0.0.0.0 dashboard origin and stop non-square SVG image warnings (#11269)
Validated on the combined 8-PR board: live-server-allowlist suite green within the board's 88/88, typecheck:core + dashboard-typecheck clean. 0.0.0.0 as a browser Origin is loopback-equivalent (it can never name a LAN host — same treatment as headroom/detect.ts and outboundUrlGuard.ts), so the local-only posture is unchanged and the FORBIDDEN_ORIGIN reconnect flood on the dev server's printed URL stops. Thank you @Minamaged18!
2026-08-23 18:10:57 -03:00
Prajeeth H
ab150e1f2b test(startup): assert disabled boot path log output at runtime (#11016) (#11265)
Validated on the combined 8-PR board: 88/88 across the board's focused suites, typecheck:core + dashboard-typecheck clean, static gates within baseline. The subprocess spawn this test does timed out locally on the shared devbox under load 35 (ETIMEDOUT on tsx bootstrap — environment, not the test); CI runs it unloaded. Runtime log-output assertion for the disabled credential-health boot path, closing the #11016 follow-up suggested on #11029. Thank you @Prajeeth-12!
2026-08-23 18:10:54 -03:00
Harvey Doan
9adeb3b673 fix(providers): clamp reasoning_effort to the declared vocabulary of models that expose one (#11274)
Validated on the combined 8-PR board: the declared-vocabulary clamp integrates with #11232's learned-set clamp (both fire in sequence; REASONING_EFFORT_ORDER import added), reasoning quartet 57/57 including the new opencode-go suite 7/7, 88/88 across the board's focused suites, typecheck:core + dashboard-typecheck clean, all static gates within baseline. Retargeted main→release/v3.8.50 and rebased onto the release tip (authorship preserved; the branch carried main history, so only the real commit was carried). The generic explicit-capability clamp closes the Console Go 400 [1210] loop for models with a declared effort vocabulary. Thank you @linhdmn — the live-probe table in the PR body is exactly the evidence standard we want.
2026-08-23 18:10:21 -03:00
Armin Anton” ∴
10276821cd Integration: security tier + self-hosted operator blockers (rebased onto v3.8.51) (#10952)
Validated on the resolved merge against the current tip (527da656 + the post-#11281 rebaseline): the single conflict was a comment-only collision in providers/[id]/models/route.ts (kept the tip's #10828-ordering note). Focused suites 125/125 across all 13 touched test files (build-sqlite-stub, cc-compatible, copilot-claude-messages, copilot-gemini-route, executor-github, ghe-copilot, github-copilot-discovery-token, github-copilot-model-discovery, noauth-sibling-7620, provider-header-profiles, provider-models-config, request-log-payloads, upstream-error-passthrough), typecheck:core clean, file-size/changelog-integrity OK. Merged --admin over the inherited 2026-08-23 base-red cluster (#9985) — the reds are proven tip failures (CLI catalog cluster + @testing-library allowlist, being drained by #11280), not from this diff. Note: the rebase means several items the body listed (relay x-relay-path SSRF, /v1/search blocked-providers, #10736 rotation fence, #10903, #10865, #10899, #10916) already landed upstream and are NOT in this delta — the delta is: better-sqlite3 build guard + build heap/worker caps + telemetry-off (#10060 re-derived), credential-echo passthrough refusal + OCR/moderation redaction + call-log key redaction, Copilot CLI 1.0.81-6 wire identity + Claude→/v1/messages name-matched routing + discovery token fix, CC model_not_found 400, compat overrides for no-auth aliases (#7620-pinned). The Copilot wire-identity change is the one to watch in production. Thank you @arminanton — and the ported-author credits in the commit history (@rqzbeh, yidecode, the #10899/#10916 authors) are preserved. Your config-posture finding (REQUIRE_API_KEY default vs 0.0.0.0) is noted for a maintainer decision, as you scoped it.
2026-08-23 16:51:25 -03:00
Diego Rodrigues de Sa e Souza
bdf63d2171 fix(security): harden codex app-server transport (#11205 post-merge review) (#11281)
TDD: 4 red-to-green tests reproducing the two review findings + 6 new cases; 30/30 in tests/unit/codex-app-server.test.ts; typecheck/eslint/env-doc-sync/file-size clean. Merged --admin over the inherited 2026-08-23 base-red cluster (#9985): the remaining reds (CLI catalog/registry tests, @testing-library allowlist) are proven tip failures unrelated to this diff — shard logs show only CLI-cluster failures, and this PR itself drains the mutation-test-coverage red (stryker registration for #11267's test). Behavior change for app-server deployments is documented in the PR body (sandbox default + binding refusal).
2026-08-23 16:49:19 -03:00
Rafa Martins
527da6565d feat: list embeddings from configured providers (#11249)
Validated: qdrant-routes integration suite 19/19 on the rebased branch, typecheck:core clean. I retargeted the PR from main to release/v3.8.50 and rebased your single commit onto the release tip (authorship untouched) — no content changes. Embedding models now list from configured/credentialed providers via the embedding registry, with vector dimensions in labels and the unconfigured OpenAI fallback removed. Thank you @rafacpti23!
2026-08-23 14:42:09 -03:00
Diego Rodrigues de Sa e Souza
d077e88456 fix(providers): complete Hack Club AI removal from shared catalog (#11176) (#11262)
* fix(providers): complete Hack Club AI removal from shared catalog (#11176)

PR #11118/#11123 removed hackclub from the open-sse REGISTRY but the
canonical shared catalog kept the entry, so the dashboard, alias resolver,
icon registry, onboarding i18n strings and the generated provider reference
kept advertising a provider the router no longer serves.

Removed:
- APIKEY_PROVIDERS hackclub entry (id + "hc" alias) in apikey/gateways.ts
- hackclub from ProviderIcon KNOWN_SVGS + public/providers/hackclub.svg asset
- providers.onboardingProviderDescriptions.hackclub from all 43 locales
- stale comments referencing hackclub as a living provider (web-cookie.ts,
  registry/huggingchat, registry/g4f-groq, registry/freetheai, test prose)

Count cascade 351 -> 350 (measured per-file; the live catalog union across
all 11 provider collections goes 351 -> 350):
- README.md, AGENTS.md, llm.txt + 42 i18n llm.txt mirrors (byte-identical
  bodies, docs-sync gate green), package.json description
- docs/reference/PROVIDER_REFERENCE.md regenerated (gen-provider-reference)
- canonical numbers in readme-hero/promise-pillars/comparison-table/
  cli-terminal SVGs (docs-counts-sync STRICT gate green)

Kept intentionally (historical records, not catalog):
- CHANGELOG.md + docs/i18n/*/CHANGELOG.md entries from when the provider
  was added (#2339, #2611) — release history
- src/lib/db/migrations/162_remove_hackclub_provider.sql — the removal
  migration itself
- tests/unit/remove-hackclub-11118.test.ts — the REGISTRY removal guard

Validation: new tests/unit/hackclub-removed.test.ts (5 asserts: catalog
absence, hc alias free, structural grep over provider sources, icon/asset
gone, i18n key gone) fails before / passes after; provider sibling tests
46 pass; provider-catalog consumer batch 268 pass; typecheck:core clean;
eslint clean on touched files; check:provider-consistency OK (350
canonical); check:docs-counts-sync + check:docs-sync green.

Closes #11176

* test(providers): align APIKEY split count after hackclub removal (232 -> 231) (#11176)

---------

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 14:40:12 -03:00
Dizzle
00c80fd14a feat(models): surface learned reasoning_effort sets in catalog, variants, and dispatch (#11252)
Validated on the combined 12-PR batch board + the resolved merge against the post-#11232 tip: focused suites 73/73 (learned-reasoning-effort-caps, synced-capabilities-learned-effort-override, synced-effort-suffix-learned-validation, effort-tiers-loop-catalog-e2e, reasoning-effort-clamp-and-retry, reasoning-effort-learned-capability) + opencode-plugin effort-tier-variants 4/4, typecheck:core clean, gates within baseline. The stacked-branch conflict after #11232 squash-landed was resolved by hand (the learned-caps module keeps both the Set API and the new model-scoped lookup). The effort_tiers loop is closed end-to-end: catalog advertises exactly what the upstream accepts, and -<tier> suffix variants resolve against the learned set. Thank you @maxmad64bis!
2026-08-23 14:38:57 -03:00
Diego Rodrigues de Sa e Souza
7c2dba0b9b feat(monitoring): expose structural chat admission snapshot + shed counters (#11244) (#11268)
The structural admission gate (src/shared/middleware/chatBodyAdmission.ts —
the bounded heavyweight lease + healthy-headroom path from #10110/#10437)
returns its 503 chat_admission_busy BEFORE request logging, so a shed left
no trace: no counter, no log line, and the process-wide snapshot was never
consumed by any route. This adds pure observability — admission behavior,
defaults, and thresholds are untouched.

- chatBodyAdmission.ts: in-memory shed history (shedTotal + shedsByReason)
  on ChatAdmissionController, recorded at the two capacity-driven give-up
  points in acquireHeavyWithin (queue_timeout when the bounded wait
  expires, queued_bytes_budget when the heap valve refuses to park). A
  client abort mid-wait is deliberately not counted — capacity was never
  denied. Each shed also emits exactly one structured pino warn (module
  chat-admission) with reason/activeHeavy/waiting/queuedBytes and the HMAC
  session fingerprint — never a raw credential. PerConnectionAdmission
  Controller.snapshot() now carries the counters plus activeHealthyHeadroom.
- /api/monitoring/health: the structural snapshot is exposed under a new
  additive chatAdmission key next to the existing adaptiveAdmission (the
  shadow-mode layer) — allowlisted projection in observability.ts, nothing
  removed from the current payload.
- Tests: tests/unit/chat-admission-visibility-11244.test.ts (RED→GREEN:
  shed counting per reason, abort exclusion, snapshot shape, and the warn
  log carrying the fingerprint but never the raw API key) + a chatAdmission
  allowlist-projection test in observability-payloads.test.ts.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 14:29:32 -03:00
Diego Rodrigues de Sa e Souza
92a083ab8c fix(resilience): honor dashboard quota snapshots in opencode-go preflight (#11234) (#11267)
The opencode-go quota preflight ignored the dashboard quota snapshots, so
priority combos kept selecting connections whose weekly window was already
drained. Two gaps, two fixes:

A) fetchOpencodeQuota only consulted the live upstream endpoint, which has
   no public quota API (404 — the module JSDoc already admits this). Every
   preflight therefore evaluated null and proceeded (fail-open) even with a
   connection at 0% weekly remaining in plain sight on the dashboard. The
   fetcher now synthesizes its triple-window QuotaInfo from the cached
   dashboard snapshots when the live endpoint yields nothing, mapping
   session→window_5h, weekly→window_weekly, mcp_monthly→window_monthly and
   mirroring getQuotaWindowStatus semantics (expired resetAt = window rolled
   over = must not count as exhausted; fractionReported=false = unknown,
   never exhaustion). Read-only via src/domain/quotaCache.ts accessors —
   never SQL, never a re-scrape on the hot path — and gated on the
   connection actually having dashboard scrape config, so unconfigured
   connections never touch the snapshot store. Fail-open is preserved:
   no snapshots → null, exactly as before. The quotaCache import is dynamic
   because a static edge would close an initialization cycle
   (fetcher → quotaCache → usage.ts → usage/opencode.ts → fetcher).

B) The sibling-selection latency gate in getProviderCredentialsWithQuotaPreflight
   never consulted resilience.quotaPreflight.enabled
   (QUOTA_PREFLIGHT_CUTOFF_ENABLED) — that flag only armed the auto-strategy
   candidate builder and the per-target cutoff for pinned connections, so a
   priority combo over sibling opencode-go connections (connectionId null at
   combo level) skipped preflight entirely. The flag now arms the gate as
   well; the default (flag off) is unchanged.

TDD (Hard Rule #18), tests/unit/quota-exhaustion-cutoff-opencode.test.ts:
- fetcher 404 + seeded snapshots weekly=0%/session=80% → cutoff blocks
  (RED before, GREEN after); also asserts the bridge is read-only (single
  upstream fetch, no re-scrape).
- weekly 0% with next_reset_at in the past → not blocked (window dropped).
- per-window threshold override resolves against the mapped window_weekly
  key (50% override blocks at 40% remaining; factory 2% does not).
- fail-open guard: configured dashboard with no snapshots still returns null.
- selector level: flag on, two opencode-go sisters, priority-1 exhausted →
  selection skips to the healthy one (RED before, GREEN after).

Sibling suites green: opencode-quota-fetcher (18), quota-preflight,
combo-priority-quota-exhaustion-cutoff-5923, issue-6686, 8431, throttle-6911,
sse-auth*, quota fetchers, combo strategies, snapshot/hydration tests
(~500 tests). eslint (with suppressions) and typecheck:core clean.

Closes #11234

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 14:28:19 -03:00
Dizzle
5b92dbded1 feat(lint): add no-unused-vars ratchet scoped to src+open-sse+tests (#11247)
Validated on the combined 12-PR batch board: typecheck:core clean, file-size/changelog/complexity/cognitive gates within baseline, eslint config smoke-tested. Freeze-then-ratchet for @typescript-eslint/no-unused-vars scoped to src/open-sse/tests (1393 pre-existing frozen, _ escape hatch, args:all), following the #7879 pattern — plus it untracks the two docs/superpowers planning files that leaked in via #11213 and were tripping check:tracked-artifacts for everyone. Thank you @maxmad64bis!
2026-08-23 14:26:43 -03:00
Diego Rodrigues de Sa e Souza
5cf16028fe fix(cli): real OpenRouter key validation + auth export argument wiring (#11226) (#11264)
Two defects exposed by #11226 (the 401 "User not found." itself is upstream
OpenRouter's response to a bad key — not an OmniRoute bug):

1. OpenRouter key validation was vacuous. Both the dashboard Check (via
   validateProviderApiKey -> validateOpenAILikeProvider) and 'omniroute
   providers test' (bin/cli/provider-test.mjs) probed /api/v1/models, which is
   PUBLIC and answers 200 to any key — so invalid keys were saved/marked valid
   and only failed on real chat traffic. OpenRouter's authenticated key-info
   endpoint (GET /api/v1/auth/key, 200 = valid / 401 = invalid) is now the
   probe: registered as testKeyModelsUrl on the openrouter registry entry
   (same mechanism as perplexity) and as keyCheckPath in the CLI test configs.
   No other provider's probe changes; error results keep using canned strings,
   never the raw upstream body (Hard Rule #12).

2. 'omniroute auth export' crashed with "cmd.optsWithGlobals is not a
   function". .command("auth export") does not register a two-word command:
   commander parses the bare word 'export' as a required positional argument,
   so the action received (exportArgValue, options, command) while expecting
   (options, command). Registered 'export' as a proper nested subcommand of
   'auth' — the documented CLI surface 'omniroute auth export [--force]
   [--id] [--format] [--out]' is unchanged, and unknown positionals
   (e.g. 'omniroute auth bogus') are now rejected instead of silently running
   the export.

TDD: tests/unit/openrouter-key-validation-auth-endpoint.test.ts (stub mimics
the real OpenRouter: /models public-200, /auth/key 401 'User not found.') and
tests/unit/cli-auth-export-wiring.test.ts (real commander wiring via
createProgram) were RED before the fix and are GREEN after.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 14:26:08 -03:00
crmbadesaba-commits
b5e4c2c0ce docs(i18n): add complete Persian user guide translation (#11254)
Validated on the combined 12-PR batch board: check:docs-all passes (doc-links + fabricated-docs strict). Complete Persian USER_GUIDE translation with preserved commands, identifiers and fixed relative links. Thank you @crmbadesaba-commits!
2026-08-23 14:25:14 -03:00
ismail çelik
af90cb7f9b docs(i18n): improve and complete Turkish documentation translations (#11237)
Validated on the combined 12-PR batch board: check:docs-all passes (docs-sync, doc-links over 855 links, fabricated-docs strict). 26-file Turkish documentation suite at full parity with consistent terminology. Thank you @ismailcelik-tr!
2026-08-23 14:25:09 -03:00
Diego Rodrigues de Sa e Souza
578db866a4 fix(cli): complete Windows cliproxy platform handling + pid probe (#11236) (#11263)
Residuals of #11236 after #10371/#10491 landed on the tip:

- Dist-fold residuals (bugs 2+3): managedBinaryName() (binaryManager),
  resolveSpawnArgs() (installers/cliproxy) and the per-OS memory probes in
  getProcessInfo() (processManager) still read the process.platform literal,
  which the Linux build of the published artifact constant-folds (precedent:
  b43a212680 / #10244). Converted to call-time os.platform() reads, matching
  the module's documented anti-fold pattern. Test-side process.platform uses
  are not bundled and stay.
- Fold guard: new tests/unit/windows-platform-fold-guard-11236.test.ts pins
  zero out-of-comment process.platform occurrences in the four artifact
  runtime files, with a comment-stripping tokenizer plus mutation self-checks.
- Bug 6 (pid null on Windows): portProbe.resolvePortPid() only probed
  lsof/ss/net-tools netstat. Added a netstat -ano probe with a dedicated
  LISTENING-row parser (parseWindowsNetstatPid) as the last fallback; Unix
  probes unchanged, and the Windows parser never matches Unix rows (LISTEN vs
  LISTENING). Also converted the darwin args branch in the same array to
  os.platform() (same fold class, same hunk).
- Bug 5 hardening: runOAuthStatus coerces an out-of-contract 200 payload to
  an empty list with a sanitized stderr warning instead of crashing on
  .filter over a non-array.

TDD: guard test, parser tests and the oauth hardening test all failed RED
before the fix and pass GREEN after; sibling suites (binaryManager,
processManager, portProbePid, cli-oauth-commands, installers,
ServiceSupervisor, version-manager) green. The 6877 spawn-args test's win32
mock moved from defineProperty(process.platform) to
mock.method(os, "platform") to match the new runtime read — assertion
unchanged.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 14:25:04 -03:00
Paco Cartones
e32b9264e8 fix(cli): resolve dynamic imports to file:// URLs so the DB fallback works on Windows (#11238)
Validated on the combined 12-PR batch board: cli-combo-command + windows-esm-import-paths suites pass, typecheck:core clean. pathToFileURL on the four dynamic-import call sites unbreaks the CLI offline DB fallback on Windows. Thank you @pacocartones!
2026-08-23 14:24:50 -03:00
Paco Cartones
a55ee5dc05 feat(combo): make the global attempt budget operator-configurable (#11134) (#11239)
Validated on the combined 12-PR batch board: combo-max-global-attempts-config 4/4 plus the neighboring combo suites green, typecheck:core clean, gates within baseline. clampGlobalAttempts mirrors clampComboDepth with a 200 hard cap, so a bad config can never disable the budget. Closes the configurability item from #11134. Thank you @pacocartones!
2026-08-23 14:24:45 -03:00
Paco Cartones
e0a22ff619 test(cli): make the CLI suite pass on Windows (#11240)
Validated on the combined 12-PR batch board: the touched CLI test files pass (alias-resolver-7791, run-command — incl. the new shellArgs helper), typecheck:core clean. Test-side only, no production behavior change. Thank you @pacocartones!
2026-08-23 14:24:15 -03:00
Paco Cartones
162ef913da fix(usage): order quota windows chronologically on every provider card (#11241)
Validated on the combined 12-PR batch board: repro-7764 suite 17/17 on this tree (11/17 fail on a clean tip without the fix — proper red-to-green), typecheck:core clean, gates within baseline. Quota windows now order chronologically from the data shape instead of a provider whitelist. Thank you @pacocartones!
2026-08-23 14:24:05 -03:00
Diego Rodrigues de Sa e Souza
158c6ec233 fix(embeddings): honor configured LM Studio connection URL via lm-studio alias (#11233) (#11260)
The dashboard stores LM Studio connections under the hyphenated provider id
"lm-studio", but the embedding registry keys the provider as "lmstudio"
with no alias. As a result, "lm-studio/<model>" embedding requests failed
with a 400 unknown-provider error, and "lmstudio/<model>" requests always
hit the hardcoded http://localhost:1234/v1/embeddings endpoint, ignoring the
baseUrl of the configured connection.

Mirror the ollama-local pattern from #2824/#9225:

- embeddingRegistry: add "lm-studio" -> "lmstudio" to
  EMBEDDING_PROVIDER_ALIASES (registry key unchanged so existing
  "lmstudio/<model>" clients keep working).
- embeddings service: extend the optional keyless-connection hydration to
  lmstudio; getProviderCredentials("lmstudio") already resolves the
  "lm-studio" connection via the provider search pool/alias, and a
  selection/rate-limit failure still proceeds without credentials.
- embeddings handler: apply the same baseUrl override + normalization
  (strip trailing slashes and /v1, /v1/chat/completions, /v1/embeddings
  suffixes, then rebuild <host>/v1/embeddings) to lmstudio, keeping the
  static localhost fallback when no connection or empty baseUrl.

TDD: tests/unit/lmstudio-connection-baseurl-11233.test.ts failed on the
alias, override and service-hydration asserts before the fix and passes
after; ollama-local (#2824) and lmstudio registry (#7601) sibling tests
remain green.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 14:23:52 -03:00
Natizh
34463f6b36 docs(i18n): restore Italian README translation (#11246)
Validated on the combined 12-PR batch board: docs gates (check:docs-all incl. doc-links + fabricated-docs strict) all pass. Italian README restored to a real translation and re-synced with the canonical root README. Thank you @Natizh — and thank you for the sharp analysis of the translation-pipeline skip logic; worth a follow-up issue.
2026-08-23 14:23:36 -03:00
Dizzle
a054ac408f feat(providers): allow per-connection maxWaitMs rate-limit override (#11251)
Validated on the combined 12-PR batch board: focused node:test suites green (incl. provider-rate-limit-overrides-schema + ratelimit-admission-control-6593 isolated 11/11 + the new EditConnectionModal vitest 3/3), typecheck:core clean, all static gates within baseline. Pushed one follow-up commit to your branch with the real Vietnamese translations for the two new keys (repo convention: vi never ships __MISSING__ placeholders). Per-connection maxWaitMs override lands, folding the zai-web exception into the general mechanism. Thank you @maxmad64bis!
2026-08-23 14:21:55 -03:00
Dizzle
7fdd2e0f2a fix(sse): learn accepted reasoning_effort sets and clamp downgrade-only (#11232)
Validated on the combined 12-PR batch board (worktree off origin/release/v3.8.50 @ 8f390eff): focused node:test suites 183/184 (the single red was a load-induced pollUntil flake — 11/11 when re-run isolated, this file included), typecheck:core clean, file-size/changelog/complexity/cognitive gates all within baseline, mutation-coverage gate no-drift. Learned effort sets now cost at most one 400 per provider+model. Thank you @maxmad64bis!
2026-08-23 14:21:27 -03:00
Diego Rodrigues de Sa e Souza
b81f2b646a fix(build): align pack-boot sql.js expectations with dependency-based packaging (#11242) (#11266)
check:pack-artifact and check:pack-boot have been self-contradictory since
05/08, blocking the v3.8.50 publish in ci.yml (build:cli job) and
npm-publish.yml:

- check:pack-artifact FAILS any tarball path containing a node_modules
  segment (PACK_ARTIFACT_NEVER_ALLOWED_SEGMENTS; files[] also excludes
  "!**/node_modules/**").
- check:pack-boot REQUIRED sql.js under the vendored
  dist/node_modules/sql.js location — a path the tarball can never carry,
  so both gates could never be green at once.

The packaging model is now dependency-based: sql.js and node-machine-id
are declared `dependencies` (a clean install places them under
<packageRoot>/node_modules/), and better-sqlite3 is an optionalDependency
installed natively per platform (^13.0.2 — which also covers the
darwin-arm64 prebuild gap from #11242 by construction). The runtime
already resolves the WASM at <cwd>/node_modules/sql.js/dist/sql-wasm.wasm
(src/lib/db/adapters/sqljsAdapter.ts).

Changes:
- scripts/check/check-pack-boot.mjs: REQUIRED_SQLJS_RUNTIME_FILES now
  points at node_modules/sql.js/{package.json,dist/sql-wasm.js,
  dist/sql-wasm.wasm} — the dependency-installed location the clean-prefix
  install actually produces. REQUIRED_MACHINE_TOKEN_RUNTIME_FILES was
  already correct and is unchanged.
- bin/cli/runtime/sqliteRuntime.mjs: BETTER_SQLITE3_VERSION bumped
  ^12.10.1 -> ^13.0.2 to match optionalDependencies (the lazy runtime
  install was pulling the wrong major), and exported for the guard.
- tests/unit/pack-boot-runtime-paths.test.ts (new, TDD: RED -> GREEN):
  pins that (a) no pack-boot required path references a never-publishable
  vendored dist/<segment> location (driven by
  PACK_ARTIFACT_NEVER_ALLOWED_SEGMENTS), (b) sql.js/node-machine-id stay
  declared dependencies, (c) the lazy-install spec stays on the declared
  optionalDependency major.
- tests/unit/check-pack-boot.test.ts: the sql.js contract test pinned the
  old vendored path; updated to node_modules/sql.js/dist/sql-wasm.wasm.
  This is alignment to the real new contract (vendoring ended), not
  masking — the same test still asserts the find-missing behavior.

Electron is unaffected: the vendored dist/node_modules bundle still
exists for Electron packaging (postinstall.mjs and assembleStandalone.mjs
untouched).

Refs #11242
Refs #10296

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 14:15:14 -03:00
Diego Rodrigues de Sa e Souza
a7e09eda5c fix(dashboard): restore ProviderModelsModal map broken by #11228 (base-red #9985) (#11256)
The squash merge of #11228 applied its endpoint-header hunk inside
ProviderModelsModal, replacing the groupModels.map callback's return
statement with the page-level guided header JSX. The file no longer
parsed (Turbopack: 3 errors at line 2397; release-green reported the
same defect as '1 ESLint error'), red-ing every Build App / Docker
publish run since 8a42aeebb8.

Surgical revert of that single hunk: the file is byte-identical to its
pre-#11228 state. The rest of #11228 (health page verdict header,
resilience reassurance, i18n keys) parses fine and stays.

Validation: prettier parse OK; EndpointPageClient.test.tsx 4/4 (the
pre-existing jsdom render suite imports the component, so it is the
permanent regression guard); diff vs pre-#11228 empty.

Refs #9985

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 13:17:24 -03:00
Markus Hartung
855243ab18 fix(dashboard): repair EndpointPageClient JSX + place guided header in main return (#11228 follow-up)
The #11228 hunk spliced the guided endpoint header into ProviderModelsModal's
renderModelGroup map callback, replacing its return statement and leaving an
unclosed <div> — dashboard typecheck failed on the release tip. Restore the
modal's map return and render the header (title/subtitle//v1 URL/test link/
advanced-protocols note) at the top of the main component return, using the
i18n keys the PR added (endpoint.title/subtitle/testEndpoint/advancedProtocols)
and the existing displayBaseUrl variable.

Also untrack two docs/superpowers planning files that leaked in via #11213;
they belong to _tasks/ (copies preserved there) and their tracked presence
trips check:tracked-artifacts on every commit.

Validated: check:dashboard-typecheck OK (220 pre-existing, all within frozen
baseline; zero syntax errors in EndpointPageClient.tsx).
2026-08-23 13:00:40 -03:00
Armin Anton” ∴
8f390efffd feat(codex): self-contained codex app-server transport (executor + provider + sign-in) (#11205)
Merged after conflict resolution: the 5 conflicting test files were the base-red drains that #11201 already landed on the tip — kept the tip versions; the feature content is untouched. Validated on the combined batch board + this branch: codex-app-server + codex-gpt56-catalog 25/25, typecheck:core clean, docs-counts green (351 providers), provider-consistency 268/351/0. The opt-in codex-app-server transport (JSON-RPC-over-WS, turn/completed-awaited close, Responses SSE bridge) leaves the default codex path untouched. Thank you @arminanton — a 3.4k-line transport with the docs wave and tests to match!
2026-08-23 10:20:06 -03:00
Rafa Martins
968fa96105 feat: guide Qdrant memory configuration (#11213)
Merged after conflict resolution (validated on the combined batch board + this branch): component integrated with #10489's health-race semantics (stale-check invalidation, 3-state badge, correct useCallback deps — your validation gate and tutorial are preserved on top); the two pre-gate tests updated to validate-search-before-enable (contract propagation, commented); the docs/superpowers planning files were dropped — project rule keeps planning artifacts out of docs/ (they live in the private _tasks/ repo). Base was mistakenly main; retargeted. qdrant-config-card 7/7 + qdrant-routes integration 18/18. Thank you @rafacpti23 — the pre-enable real-search gate closes a real misconfiguration footgun!
2026-08-23 10:13:31 -03:00
Rafa Martins
c8369193c1 fix: add AWS Polly signing credentials (#11207)
Merged after conflict resolution (validated on the combined batch board + this branch): stale drift files (package.json/package-lock/.gitignore) kept at tip; the two modals merged additively — AWS SigV4 fields coexist with the chatgpt-web-codex tunnel fields and the #11156 Enter-handler mirror (vitest 2/2 re-run). file-size gate green with the dated AddApiKeyModal 1173 entry (owner-authorized). aws-polly modal + provider-validation-specialty 127/127. Base was mistakenly main; retargeted to release/v3.8.50. Credentials stay in the protected field; nothing logged. Thank you @rafacpti23!
2026-08-23 10:09:07 -03:00
adevwithpurpose
90ba281e7f fix(sse): default single-target incompatible reasoning to drop for agentic replay (#10959) (#11178)
Merged after conflict resolution onto the post-#10961 tip (verified no clobber of today's plaintext-wins work — the resolver functions were appended and the chatCore call-site swapped; a first --theirs attempt was caught reverting #10961 and redone hunk-by-hunk). resolveIncompatibleReasoningAction now defaults single-target incompatible reasoning to drop while combos keep their explicit strategy, with the x-omniroute-reasoning-fallback header override. 21/21 reasoning suites green, typecheck clean. Fixes #10959. Thank you @adevwithpurpose!
2026-08-23 10:00:17 -03:00
小妍儿 ✨
84bd382d94 fix(kie): map the Nano Banana 2 Market id to its KIE upstream id (#11225) (#11231)
Validated on the combined batch board: gates clean, typecheck clean, focused tests green.

Exactly one Market id rewritten at the createTask seam (google-imagen/nano-banana-2 → nano-banana-2); every other namespaced id forwards byte-identical — the contract is stated and tested precisely. Fixes #11225. Thank you @xiaoyaner0201!
2026-08-23 09:48:48 -03:00
Tuan Dinh
8d59ab363b feat(cli): detach tray mode from terminal (#11230)
Validated on the combined batch board over tip 0b41259f: static gates clean, typecheck:core clean, 430+ focused tests green across 5 groups.

--tray returns after readiness and survives terminal close, with tray-mode autostart on macOS/Windows/Linux while headless Linux keeps the systemd user service. tray-detached + autostart suites green. Closes #11229. Thank you @tuandinh0801!
2026-08-23 09:48:16 -03:00
aliyosufi
fb421bc580 fix(build): spawn esbuild cross-platform in the postbuild hook (#11159)
Validated on the combined batch board over tip 0b41259f: static gates clean, typecheck:core clean, 430+ focused tests green across 5 groups.

postbuild's esbuild spawn now resolves cross-platform (no more ENOENT after a successful Next compile on Windows). build-tool-runner-win-shim suite green. Thank you @aliyosufi — first contribution, welcome!
2026-08-23 09:48:12 -03:00
Harvey Doan
3d8448b45e fix(sse): floor muse-spark output budget to prevent empty-content 502s (#11214)
Validated on the combined batch board over tip 0b41259f: static gates clean (changelog, file-size 160 frozen, complexity 2628<=2774, cognitive 1187<=1223, dead-code 408<=416, docs-counts green at 351 providers, provider-consistency 268/351/0), typecheck:core clean, 430+ focused tests green across 5 groups.

muse-spark's all-reasoning empty-answer payloads (41 failures in 2h captured live) now floor the output budget so the model can actually emit content — no more empty-content 502 churn. Thank you @linhdmn!
2026-08-23 09:47:10 -03:00
Harvey Doan
e66181b182 fix(sse): append synthetic user turn for GLM-family upstreams (400 [1214]) (#11209)
Validated on the combined batch board over tip 0b41259f: static gates clean (changelog, file-size 160 frozen, complexity 2628<=2774, cognitive 1187<=1223, dead-code 408<=416, docs-counts green at 351 providers, provider-consistency 268/351/0), typecheck:core clean, 430+ focused tests green across 5 groups.

GLM-family upstreams reject message arrays with no user turn (400 [1214], verified live 2026-08-23); the synthetic user turn keeps Claude Code sessions on opencode-go alive. Thank you @linhdmn!
2026-08-23 09:47:07 -03:00
Jonathan Bailey
7af14d2696 fix(codex): prefer max_context_window over context_window as the usable input limit (#11179)
Validated on the combined batch board over tip 0b41259f: static gates clean (changelog, file-size 160 frozen, complexity 2628<=2774, cognitive 1187<=1223, dead-code 408<=416, docs-counts green at 351 providers, provider-consistency 268/351/0), typecheck:core clean, 430+ focused tests green across 5 groups.

max_context_window now wins over the pricing-tier context_window in Codex catalog parsing — context-aware fallback stops demoting codex behind smaller targets. Live evidence (390K served past 272K) plus the live-shape regression test. Thank you @excessivechaos!
2026-08-23 09:47:03 -03:00
Armin Anton” ∴
1135cbea80 feat(cli-tools): add Prime Agent to the CLI agents catalog (#11166)
Validated on the combined batch board over tip 0b41259f: static gates clean (changelog, file-size 160 frozen, complexity 2628<=2774, cognitive 1187<=1223, dead-code 408<=416, docs-counts green at 351 providers, provider-consistency 268/351/0), typecheck:core clean, 430+ focused tests green across 5 groups.

Prime Agent joins the CLI agents catalog with runtime entry + doc counts synced (35 tools; CLI-TOOLS.md row). cli-catalog-acpspawnable 26/26. Thank you @arminanton!
2026-08-23 09:47:00 -03:00
Mark Yan
6e9553eb93 pricing: note DeepSeek peak is weekdays only (#11210)
Validated on the combined batch board over tip 0b41259f: static gates clean (changelog, file-size 160 frozen, complexity 2628<=2774, cognitive 1187<=1223, dead-code 408<=416, docs-counts green at 351 providers, provider-consistency 268/351/0), typecheck:core clean, 430+ focused tests green across 5 groups.

Comment-only correction verified against the vendor page wording: DeepSeek peak windows are Monday-Friday (35h/week), prices unchanged. Thank you @xyzs996 — precise sourcing, both language footnotes reconciled!
2026-08-23 09:46:56 -03:00
551 changed files with 30870 additions and 15032 deletions

View File

@@ -65,6 +65,12 @@ INITIAL_PASSWORD=CHANGEME
# OMNIROUTE_RELEASE_REF=origin/main
# OMNIROUTE_ALLOW_CANARY_BUILD=1
# Build-phase signal (#10060). Set to 1 by scripts/build/build-next-isolated.mjs and
# inherited by every spawned build worker so the DB layer returns a no-op stub instead
# of loading the native better-sqlite3 addon (which aborts the worker on exit).
# Never set this for the running server. Used by: src/lib/buildPhase.ts, src/lib/db/core.ts
# OMNIROUTE_BUILDING=1
# Encryption key for SQLite database encryption at rest.
# Used by: src/lib/db/encryption.ts — encrypts the entire SQLite database.
# Generate: openssl rand -hex 32 | Leave empty to disable DB encryption.
@@ -1021,6 +1027,16 @@ PROVIDER_LIMITS_SYNC_SPACING_MS=1500
# Used by: open-sse/services/compression/engines/rtk/filterLoader.ts. Default: 0.
#OMNIROUTE_RTK_TRUST_PROJECT_FILTERS=0
# Maximum concurrent synchronous compression workers. Excess jobs wait FIFO.
# Used by: open-sse/services/compression/compressionWorkerPool.ts. Default: 2.
#OMNI_COMPRESSION_WORKERS=2
# Per-job worker timeout (ms). A timed-out worker is terminated and the request fails open.
# Used by: open-sse/services/compression/compressionWorkerPool.ts. Default: 120000.
#OMNI_COMPRESSION_WORKER_TIMEOUT_MS=120000
# Terminate idle compression workers after this many milliseconds.
# Used by: open-sse/services/compression/compressionWorkerPool.ts. Default: 60000.
#OMNI_COMPRESSION_WORKER_IDLE_MS=60000
# T02 stacked-pipeline engine circuit-breaker (OPT-IN, default off). When enabled, a compression
# engine that throws repeatedly across requests is skipped (fail-open) for a cooldown.
# Used by: open-sse/services/compression/pipelineEngineBreaker.ts.
@@ -1303,6 +1319,36 @@ CURSOR_USER_AGENT="Cursor/3.4"
# set to true/1/yes to enable. Used by: open-sse/executors/codex.ts.
# OMNIROUTE_CODEX_DROP_NONSTANDARD_EVENTS=true
# Codex app-server WebSocket transport (opt-in). When a WebSocket URL and a
# capability token are both provided, Codex requests are routed through a local
# `codex app-server` sidecar over JSON-RPC instead of the HTTP Responses API.
# Each var is also settable per-connection via providerSpecificData; the env var
# is the process-wide fallback. Used by:
# open-sse/executors/codex/appServerConfig.ts.
#
# WebSocket endpoint of the codex app-server (ws:// or wss://). Required to
# enable the transport; leaving it unset keeps Codex on its HTTP transports.
# OMNIROUTE_CODEX_APPSERVER_WS=ws://127.0.0.1:8081
# Inline capability/bearer token presented to the app-server.
# OMNIROUTE_CODEX_APPSERVER_WS_TOKEN=deadbeef...
# Path to a file holding the capability token (produced by
# `codex app-server --ws-token-file <path>`). Used when the inline token above
# is not set.
# OMNIROUTE_CODEX_APPSERVER_WS_TOKEN_FILE=/run/codex-ws-token
# Working directory the app-server turn runs in (defaults to /tmp).
# OMNIROUTE_CODEX_APPSERVER_CWD=/tmp
# Approval policy passed to the app-server turn (e.g. never, on-request).
# OMNIROUTE_CODEX_APPSERVER_APPROVAL=never
# Sandbox policy passed to the app-server turn (e.g. read-only,
# workspace-write, danger-full-access). When unset, the executor defaults to
# "workspace-write" (hardened; used to be "danger-full-access").
# OMNIROUTE_CODEX_APPSERVER_SANDBOX=read-only
# Auto-approve the app-server's own approval prompts (command/file/permission
# execution on the host). Defaults to OFF — prompts are auto-denied. Set to
# true/1/yes only when you trust the deployment to run codex-decided host
# commands. Per-connection override: providerSpecificData.codexAppServerAutoApprove.
# OMNIROUTE_CODEX_APPSERVER_AUTO_APPROVE=false
# ═══════════════════════════════════════════════════════════════════════════════
# 13. CLI FINGERPRINT COMPATIBILITY (Anti-Detection)
# ═══════════════════════════════════════════════════════════════════════════════
@@ -1975,6 +2021,9 @@ APP_LOG_TO_FILE=true
# CLIPROXYAPI_HOST=127.0.0.1
# CLIPROXYAPI_PORT=5544
# CLIPROXYAPI_CONFIG_DIR=~/.cli-proxy-api
# Management key for an externally managed instance. Embedded instances use
# OmniRoute's encrypted service key.
# CLIPROXYAPI_MANAGEMENT_KEY=
# ── Mux embedded service ──
# Override the port where the embedded Mux (coder/mux) agent-orchestration

11
.gitattributes vendored Normal file
View File

@@ -0,0 +1,11 @@
# Shell scripts must always be checked out with LF line endings.
#
# On Windows, core.autocrlf=true converts text files to CRLF in the working
# tree. Scripts that are kernel-exec'd (Docker ENTRYPOINT, bin/*.sh on Linux
# hosts) then fail with `exec ...: no such file or directory` because the
# shebang becomes "#!/bin/sh\r". eol=lf overrides autocrlf for these files.
*.sh text eol=lf
# This file must stay LF too: git parses it as-is, and a trailing CR would
# corrupt every pattern (e.g. "*.sh\r" matches nothing).
.gitattributes text eol=lf

View File

@@ -2,11 +2,11 @@ name: opencode-plugin CI
on:
push:
branches: [main, release/v3.8.2]
branches: [main, "release/**"]
paths:
- "@omniroute/opencode-plugin/**"
pull_request:
branches: [main, release/v3.8.2]
branches: [main, "release/**"]
paths:
- "@omniroute/opencode-plugin/**"
types: [opened, synchronize, reopened, ready_for_review]

View File

@@ -92,5 +92,9 @@
# - x-api-key PUBLICO do Firefly web (documentado em open-sse/utils/publicCreds.ts:207);
# as duas ocorrencias sinalizadas estao em COMENTARIOS JSDoc, o runtime le de resolvePublicCred().
'''omniroute-kimi-sponsor-banner-dismissed-v\d+''',
# CheaperInference sponsor banner localStorage key (upstream #11196 /
# eb5797370). Same UI-identifier pattern as the kimi banner above, not a
# credential; the generic-api-key rule flags the long hyphenated string.
'''omniroute-cheaperinference-sponsor-banner-dismissed-v\d+''',
'''SunbreakWebUI1''',
]

View File

@@ -23,7 +23,7 @@
"scripts": {
"build": "tsup",
"clean": "rm -rf dist",
"test": "node --import tsx/esm --test tests/scaffold.test.ts tests/auth.test.ts tests/options-schema.test.ts tests/multi-instance.test.ts tests/fetch-interceptor.test.ts tests/provider.test.ts tests/gemini-sanitize.test.ts tests/combos.test.ts tests/config-shim.test.ts tests/features.test.ts tests/feature-defaults.test.ts tests/usable-combo.test.ts tests/disk-snapshot-perms.test.ts tests/fork-features.test.ts tests/auto-combo-context.test.ts tests/provider-id-routing.test.ts tests/management-read-token.test.ts tests/auto-sync.test.ts tests/model-allowlist.test.ts tests/log-level.test.ts",
"test": "node --import tsx/esm --test tests/scaffold.test.ts tests/auth.test.ts tests/options-schema.test.ts tests/multi-instance.test.ts tests/fetch-interceptor.test.ts tests/provider.test.ts tests/gemini-sanitize.test.ts tests/combos.test.ts tests/config-shim.test.ts tests/features.test.ts tests/feature-defaults.test.ts tests/usable-combo.test.ts tests/disk-snapshot-perms.test.ts tests/fork-features.test.ts tests/auto-combo-context.test.ts tests/provider-id-routing.test.ts tests/management-read-token.test.ts tests/auto-sync.test.ts tests/model-allowlist.test.ts tests/log-level.test.ts tests/effort-tier-variants.test.ts",
"prepublishOnly": "npm run clean && npm run build && npm test"
},
"keywords": [

View File

@@ -1161,6 +1161,8 @@ export interface OmniRouteRawModelEntry {
attachment?: boolean;
structured_output?: boolean;
temperature?: boolean;
/** Runtime-learned or synced reasoning tiers (server-gated, blind-mapped). */
effort_tiers?: string[];
};
release_date?: string;
last_updated?: string;
@@ -1302,6 +1304,18 @@ export function mapRawModelToModelV2(
ctx: { providerId: string; baseURL: string; apiFormat?: { anthropicPrefixes?: string[] } }
): ModelV2 {
const caps = raw.capabilities ?? {};
// effort_tiers loop: server-declared tiers become ModelV2 variants so the
// UI offers exactly the tiers OmniRoute vouches for (instead of opencode's
// invented [low, medium, high] fallback). Blind: filtering/exclusion rules
// live server-side. Absent/empty/malformed => key omitted ENTIRELY (an
// empty variants object would suppress opencode's fallback for this model).
const declaredTiers = Array.isArray(caps.effort_tiers)
? caps.effort_tiers.filter((t): t is string => typeof t === "string" && t.length > 0)
: [];
const variants =
declaredTiers.length > 0
? Object.fromEntries(declaredTiers.map((tier) => [tier, { reasoningEffort: tier }]))
: undefined;
const inMods = new Set(raw.input_modalities ?? ["text"]);
const outMods = new Set(raw.output_modalities ?? ["text"]);
@@ -1315,10 +1329,7 @@ export function mapRawModelToModelV2(
// OpenCode looks up `-m <plugin>/<combo>` as model id `<combo>` under
// the plugin provider (#10345). Other bare ids still prefix with
// `providerId` so credentials resolve as `(omniroute, model)`.
id:
raw.id.includes("/") || raw.owned_by === "combo"
? raw.id
: `${ctx.providerId}/${raw.id}`,
id: raw.id.includes("/") || raw.owned_by === "combo" ? raw.id : `${ctx.providerId}/${raw.id}`,
/**
* Display name. Falls back to raw.id when no enrichment is available;
* the caller (`createOmniRouteProviderHook`) overlays
@@ -1357,6 +1368,7 @@ export function mapRawModelToModelV2(
...(typeof raw.max_input_tokens === "number" ? { input: raw.max_input_tokens } : {}),
output: typeof raw.max_output_tokens === "number" ? raw.max_output_tokens : 0,
},
...(variants ? { variants } : {}),
status: "active",
options: {},
headers: {},

View File

@@ -0,0 +1,62 @@
/**
* effort_tiers loop — plugin maps server-declared tiers to ModelV2 variants.
* Blind mapping (I3): no owned_by/provider knowledge here — the SERVER gates
* eligibility (shouldExposeSyncedEffortVariants). Absence semantics (M3):
* no tiers => NO variants key at all (an empty object would also kill
* opencode's own fallback for non-tiered models).
*/
import test from "node:test";
import assert from "node:assert/strict";
import { mapRawModelToModelV2, type OmniRouteRawModelEntry } from "../src/index.js";
const CTX = { providerId: "omniroute", baseURL: "http://127.0.0.1:20128" } as const;
test("maps declared tiers to reasoningEffort variants", () => {
const raw: OmniRouteRawModelEntry = {
id: "oc/x-preview-f-free",
owned_by: "opencode",
capabilities: { reasoning: true, effort_tiers: ["low", "high", "max"] },
};
const model = mapRawModelToModelV2(raw, { ...CTX });
const variants = (model as unknown as Record<string, unknown>).variants as
Record<string, Record<string, unknown>> | undefined;
assert.ok(variants, "variants key present when tiers declared");
assert.deepEqual(Object.keys(variants).sort(), ["high", "low", "max"]);
assert.deepEqual(variants.max, { reasoningEffort: "max" });
assert.deepEqual(variants.low, { reasoningEffort: "low" });
});
test("no tiers => NO variants key (not an empty object)", () => {
const raw: OmniRouteRawModelEntry = {
id: "plain-model",
capabilities: { reasoning: true },
};
const model = mapRawModelToModelV2(raw, { ...CTX }) as unknown as Record<string, unknown>;
assert.equal("variants" in model, false);
});
test("empty or malformed tiers array => NO variants key", () => {
const empty = mapRawModelToModelV2(
{ id: "m", capabilities: { effort_tiers: [] } },
{ ...CTX }
) as unknown as Record<string, unknown>;
assert.equal("variants" in empty, false);
const junk = mapRawModelToModelV2(
{ id: "m", capabilities: { effort_tiers: [42, null, "ok"] as unknown as string[] } },
{ ...CTX }
) as unknown as Record<string, unknown>;
const variants = junk.variants as Record<string, Record<string, unknown>> | undefined;
assert.deepEqual(Object.keys(variants ?? {}), ["ok"], "non-string tokens dropped");
});
test("static registry entry WITH tiers also gets variants (N1 blast radius)", () => {
const raw: OmniRouteRawModelEntry = {
id: "some-static-model",
owned_by: "registry",
capabilities: { effort_tiers: ["minimal", "high"] },
};
const model = mapRawModelToModelV2(raw, { ...CTX }) as unknown as Record<string, unknown>;
const variants = model.variants as Record<string, Record<string, unknown>> | undefined;
assert.deepEqual(Object.keys(variants ?? {}).sort(), ["high", "minimal"]);
});

View File

@@ -104,7 +104,10 @@ test("models: extracts apiKey from ctx.auth (type=api) and calls fetcher with it
// #6859: dynamic-hook catalog keys use the unprefixed omnirouteProviderId
// ("omniroute"), not the OC-gate-prefixed hook.id ("opencode-omniroute") —
// that prefix must never leak into anything OmniRoute's server parses.
assert.ok(out["omniroute/claude-primary"]);
// #10345/#10821: bare combo ids (owned_by: "combo") stay unprefixed —
// OpenCode looks up `-m <plugin>/<combo>` as model id `<combo>` under the
// plugin provider, so `claude-primary` here carries no provider prefix.
assert.ok(out["claude-primary"]);
});
test("models: returns {} when ctx.auth is null/undefined/wrong-type/empty-key", async () => {
@@ -159,11 +162,15 @@ test("models: maps a sample /v1/models entry to ModelV2 (sanity)", async () => {
// omnirouteProviderId ("omniroute") — the OC-gate prefix ("opencode-")
// must stay OC-internal (hook.id / AuthHook.provider) and never leak into
// anything OmniRoute's own server parses for credential lookup.
const claude = out["omniroute/claude-primary"];
// #10345/#10821: bare **combo** ids (owned_by: "combo", e.g.
// "claude-primary") must also stay unprefixed — OpenCode looks up
// `-m <plugin>/<combo>` as model id `<combo>` under the plugin provider.
const claude = out["claude-primary"];
assert.ok(claude, "claude-primary present");
// `mapRawModelToModelV2` stamps the provider prefix on the id so OC's
// static-catalog reader resolves `(providerID, modelID)` from the key.
assert.equal(claude.id, "omniroute/claude-primary");
// `mapRawModelToModelV2` leaves bare combo ids unprefixed (see
// src/index.ts mapRawModelToModelV2) so OC's `-m <plugin>/<combo>` lookup
// resolves the combo id directly.
assert.equal(claude.id, "claude-primary");
assert.equal(claude.name, "claude-primary");
assert.equal(claude.providerID, "omniroute");
assert.equal(claude.api.id, "openai-compatible");

View File

@@ -180,6 +180,7 @@ _Living section — regenerated 2026-08-12 from all cycle commits (cycle open `e
### 🐛 Bug Fixes
- **fix(build):** every route no longer answers HTTP 500 on artifacts built from the release tip ([#11343](https://github.com/diegosouzapw/OmniRoute/issues/11343)) — `next.config.mjs` aliased `better-sqlite3` to its build-time stub **unconditionally**, on the premise that `serverExternalPackages` still won at runtime. It does not: a Turbopack `resolveAlias` rewrites the request *before* the externals check, so the request stopped matching the `better-sqlite3` external entry and the stub was baked into the shipped bundle. The sync driver then failed with `r(...) is not a constructor`, fell through `node:sqlite` and sql.js, and the instrumentation hook aborted at boot. Same failure shape as [#6344](https://github.com/diegosouzapw/OmniRoute/issues/6344), so it gets the same treatment: the alias is opt-in via `OMNIROUTE_BETTER_SQLITE3_STUB=1` through the shared `scripts/build/better-sqlite3-stub-flag.mjs` helper — set it only on a build host that actually hits the SIGABRT build-worker teardown ([#10060](https://github.com/diegosouzapw/OmniRoute/issues/10060)); default builds externalize the real native addon. Regression guards: `tests/unit/better-sqlite3-stub-alias-11343.test.mjs` (5) and the env matrix in `tests/unit/next-config.test.ts`.
- **security(search)**: block SSRF via `/v1/search` `provider_options.baseUrl` for the Firecrawl search provider — the client-controlled override is now validated as a public URL before it is used to build the server-side fetch target, so a caller with a valid API key can no longer redirect search requests at loopback, RFC1918, or cloud-metadata hosts — thanks @zmf963
- **providers**: honor `PATCH /api/providers/[id]` so `omniroute providers rotate` stops 405ing (the OpenAPI spec and CLI already use PATCH) (PR #10366)
- **cli**: route provider test commands through configured connection test endpoints (#10570)

View File

@@ -59,6 +59,12 @@ RUN set -eux; \
# ── Builder ────────────────────────────────────────────────────────────────
FROM base AS builder
# No telemetry, anywhere. Disable Next.js's anonymous build-time telemetry
# (it otherwise pings Vercel during `next build`). Set on the builder stage so
# every image build is silent; the runtime never builds, so this covers the
# only phase Next telemetry can fire.
ENV NEXT_TELEMETRY_DISABLED=1
# Build tools for native module compilation
# apt-get update needed here because base's rm -rf clears the shared cache
RUN --mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-apt-cache,target=/var/cache/apt,sharing=locked \
@@ -166,9 +172,20 @@ ENV OMNIROUTE_MITM_STUB=1
# child (build-next-isolated.mjs → resolveNextBuildEnv spreads process.env).
# Build-only; the runtime heap is set separately on the runner stage
# (OMNIROUTE_MEMORY_MB). Override: `--build-arg OMNIROUTE_BUILD_MEMORY_MB=6144`.
ARG OMNIROUTE_BUILD_MEMORY_MB=4096
# Default raised 4096 → 6144 (#10060): the Next 16 production pass on a codebase
# this size intermittently OOMs a build worker at 4 GB on memory-tight hosts.
ARG OMNIROUTE_BUILD_MEMORY_MB=6144
ENV NODE_OPTIONS="--max-old-space-size=${OMNIROUTE_BUILD_MEMORY_MB}"
# Cap Next.js build worker pools. Next 16 defaults to `os.cpus().length - 1`
# workers for page-data collection (31 on a 32-core builder); on memory-tight
# hosts 31 workers + webpack's multi-GB heap blow past RAM and a worker dies
# with SIGSEGV at teardown ("worker exited with code: null and signal: SIGSEGV"),
# silently leaving no standalone bundle. Next derives the default worker count
# from CIRCLE_NODE_TOTAL (workers = N-1), so N=8 → 7 workers: fast enough while
# fitting comfortably in RAM on any host. (#10060)
ENV CIRCLE_NODE_TOTAL=8
COPY . ./
RUN --mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-next-cache,target=/app/.build/next/cache \
mkdir -p /app/data \

View File

@@ -7,7 +7,7 @@
# 🚀 OmniRoute — The Free AI Gateway
<img src="./docs/diagrams/readme-hero.svg" width="100%" alt="OmniRoute — Never stop coding. Every AI tool → 349 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini with auto-fallback. RTK + Caveman stacked compression saves 1595% tokens (~89% avg) — never hit limits. 350 AI providers · 90+ free tiers · ~1.51B free tokens/mo · 19 routing strategies · $0 to start."/>
<img src="./docs/diagrams/readme-hero.svg" width="100%" alt="OmniRoute — Never stop coding. Every AI tool → 350 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini with auto-fallback. RTK + Caveman stacked compression saves 1595% tokens (~89% avg) — never hit limits. 350 AI providers · 90+ free tiers · ~1.51B free tokens/mo · 19 routing strategies · $0 to start."/>
</div>
@@ -210,7 +210,7 @@ curl http://localhost:20128/v1/chat/completions \
</div>
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint. 349 providers. Never stop building — OmniRoute picks the cheapest one that works. Six pillars: Never hit limits (auto-fallback across 349 providers in milliseconds, zero downtime) · Save up to 95% tokens (RTK + Caveman stacked compression cuts 1595%, ~89% avg on tool-heavy sessions) · $0 to start (90+ free tiers, 56 free forever — no card needed) · Every tool works (33 coding agents through one config) · One endpoint (OpenAI ↔ Claude ↔ Gemini ↔ Responses API at /v1) · Production-grade (circuit breakers, TLS stealth, MCP 110 tools, A2A, memory, guardrails, evals — 25,000+ tests)."/>
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint. 350 providers. Never stop building — OmniRoute picks the cheapest one that works. Six pillars: Never hit limits (auto-fallback across 350 providers in milliseconds, zero downtime) · Save up to 95% tokens (RTK + Caveman stacked compression cuts 1595%, ~89% avg on tool-heavy sessions) · $0 to start (90+ free tiers, 56 free forever — no card needed) · Every tool works (33 coding agents through one config) · One endpoint (OpenAI ↔ Claude ↔ Gemini ↔ Responses API at /v1) · Production-grade (circuit breakers, TLS stealth, MCP 110 tools, A2A, memory, guardrails, evals — 25,000+ tests)."/>
<br/>
<br/>
@@ -461,7 +461,7 @@ All **19** strategies — mix & match per combo step:
</div>
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — comparison table vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 349 providers, 90+ free providers built-in, 19 routing strategies, 12-engine token compression, built-in MCP server with 110 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA, 43 i18n UI locales, 100% MIT self-hosted. OmniRoute is the only one with the full set; competitors show a mix of checks, partials and crosses. Verified from each project&apos;s docs."/>
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — comparison table vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 350 providers, 90+ free providers built-in, 19 routing strategies, 12-engine token compression, built-in MCP server with 110 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA, 43 i18n UI locales, 100% MIT self-hosted. OmniRoute is the only one with the full set; competitors show a mix of checks, partials and crosses. Verified from each project&apos;s docs."/>
<sub>📊 Full methodology &amp; per-feature detail vs 9router, OpenRouter, CLIProxyAPI &amp; LiteLLM → [`docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md`](docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md)</sub>
@@ -612,7 +612,7 @@ the current catalog at **[radar.omniroute.online/planos](https://radar.omniroute
<b> also works with</b> · Kiro · Command Code · Antigravity · Windsurf · AMP · <b>any OpenAI-compatible tool</b>
</div>
<sub>📖 Per-tool setup for all 34 tools (26 CLI Code's + 8 CLI Agents) → [`docs/reference/CLI-TOOLS.md`](docs/reference/CLI-TOOLS.md) · 🧩 OpenCode plugin → [`@omniroute/opencode-provider`](https://www.npmjs.com/package/@omniroute/opencode-provider)</sub>
<sub>📖 Per-tool setup for all 35 tools (26 CLI Code's + 9 CLI Agents) → [`docs/reference/CLI-TOOLS.md`](docs/reference/CLI-TOOLS.md) · 🧩 OpenCode plugin → [`@omniroute/opencode-provider`](https://www.npmjs.com/package/@omniroute/opencode-provider)</sub>
</div>
@@ -646,7 +646,7 @@ of your shell history. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
</div>
> The most complete catalog of any open-source router: **349 providers**, **90+ with a free tier**, **56 free forever**.
> The most complete catalog of any open-source router: **350 providers**, **90+ with a free tier**, **56 free forever**.
<div align="center">

View File

@@ -22,8 +22,15 @@ const VALID_FORMATS = new Set(["json", "env"]);
const SECURE_FILE_MODE = 0o600;
export function registerAuthExport(program) {
// #11226: `.command("auth export")` does NOT register a two-word command — commander
// parses the bare word `export` as a required positional argument of `auth`, so the
// action received (exportArgValue, options, command) while expecting (options, command)
// and crashed with "cmd.optsWithGlobals is not a function". Register `export` as a
// proper nested subcommand instead; the CLI surface stays `omniroute auth export`.
program
.command("auth export")
.command("auth")
.description(t("authExport.description"))
.command("export")
.description(t("authExport.description"))
.option("--id <id>", t("authExport.idOpt"))
.option("--format <format>", t("authExport.formatOpt"), "json")

View File

@@ -3,6 +3,7 @@ import { printHeading } from "../io.mjs";
import { withRuntime } from "../runtime.mjs";
import { t } from "../i18n.mjs";
import { apiFetch } from "../api.mjs";
import { mcpCallTool } from "../mcpClient.mjs";
import { emit } from "../output.mjs";
import { resolveComboModels, collectModel } from "./comboModels.mjs";
@@ -63,15 +64,7 @@ export function extendComboSuggest(combo) {
weights: opts.weights ? JSON.parse(opts.weights) : undefined,
top: opts.top,
};
const res = await apiFetch("/api/mcp/tools/call", {
method: "POST",
body: { name: "omniroute_best_combo_for_task", arguments: body },
});
if (!res.ok) {
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
const data = await res.json();
const data = await mcpCallTool("omniroute_best_combo_for_task", body);
const candidates = data.candidates ?? data;
const rows = (Array.isArray(candidates) ? candidates : []).map((c, i) => ({
rank: i + 1,

View File

@@ -1,5 +1,6 @@
import { readFileSync } from "node:fs";
import { apiFetch } from "../api.mjs";
import { mcpCallTool } from "../mcpClient.mjs";
import { emit } from "../output.mjs";
import { t } from "../i18n.mjs";
@@ -78,18 +79,17 @@ async function restComboStats(period) {
}
async function mcpCall(name, args, restFallback) {
const res = await apiFetch("/api/mcp/tools/call", {
method: "POST",
body: { name, arguments: args },
});
if (res.ok) return res.json();
// 404 = MCP tool surface not mounted on this build; 501 = not implemented.
// Anything else is a genuine error and we surface it.
if ((res.status === 404 || res.status === 501) && typeof restFallback === "function") {
return restFallback();
try {
return await mcpCallTool(name, args);
} catch (err) {
// Keep the REST fallback behavior for builds where the MCP surface
// is unreachable / not mounted. Anything else rethrows as an error.
const status = err?.status || err?.cause?.status;
if ((status === 404 || status === 501) && typeof restFallback === "function") {
return restFallback();
}
throw err;
}
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
async function confirm(q) {

View File

@@ -61,27 +61,12 @@ export function registerMcp(program) {
? JSON.parse(argsPositional)
: {};
if (opts.stream) {
await runMcpStream(tool, args, globalOpts);
return;
}
const exitCode = await runMcpCallCommand(tool, args, {
...opts,
stream: opts.stream,
}, globalOpts);
const extraHeaders = opts.scope?.length ? { "X-MCP-Scopes": opts.scope.join(",") } : {};
const res = await apiFetch("/api/mcp/tools/call", {
method: "POST",
body: { name: tool, arguments: args },
headers: extraHeaders,
});
if (res.status === 403) {
process.stderr.write("Scope denied\n");
process.exit(4);
}
if (!res.ok) {
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
const data = await res.json();
emit(data, globalOpts);
if (exitCode !== 0) process.exit(exitCode);
});
mcp
@@ -99,112 +84,132 @@ export function registerMcp(program) {
const data = await res.json();
emit(data.scopes ?? data, cmd.optsWithGlobals());
});
// 5.2 — mcp tools + mcp audit
const tools = mcp.command("tools").description(t("mcp.tools.description"));
tools
.command("list")
.description(t("mcp.tools.list.description"))
.option("--scope <s>", t("mcp.tools.list.scope"))
.action(async (opts, cmd) => {
const params = new URLSearchParams();
if (opts.scope) params.set("scope", opts.scope);
const res = await apiFetch(`/api/mcp/tools?${params}`);
if (!res.ok) {
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
const data = await res.json();
emit(data.tools ?? data, cmd.optsWithGlobals(), mcpToolSchema);
});
tools
.command("info <name>")
.description(t("mcp.tools.info.description"))
.action(async (name, opts, cmd) => {
const res = await apiFetch(`/api/mcp/tools?name=${encodeURIComponent(name)}`);
if (!res.ok) {
process.stderr.write(`Not found: ${name}\n`);
process.exit(1);
}
emit(await res.json(), cmd.optsWithGlobals());
});
tools
.command("schema <name>")
.description(t("mcp.tools.schema.description"))
.option("--io <kind>", t("mcp.tools.schema.io"), "input")
.action(async (name, opts, cmd) => {
const res = await apiFetch(`/api/mcp/tools?name=${encodeURIComponent(name)}&io=${opts.io}`);
if (!res.ok) {
process.stderr.write(`Not found: ${name}\n`);
process.exit(1);
}
const data = await res.json();
const globalOpts = cmd.optsWithGlobals();
if (globalOpts.output === "json") {
process.stdout.write(JSON.stringify(data.schema ?? data, null, 2) + "\n");
} else {
emit(data.schema ?? data, globalOpts);
}
});
const audit = mcp.command("audit").description(t("mcp.audit.description"));
audit
.command("tail")
.option("--follow", t("audit.tail.follow"))
.option("--limit <n>", t("audit.tail.limit"), parseInt, 100)
.action(async (opts, cmd) => {
const { runAuditTail } = await import("./audit.mjs");
await runAuditTail({ ...opts, source: "mcp" }, cmd);
});
audit
.command("stats")
.option("--period <p>", t("audit.stats.period"), "7d")
.action(async (opts, cmd) => {
const res = await apiFetch(`/api/mcp/audit/stats?period=${opts.period}`);
if (!res.ok) {
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
emit(await res.json(), cmd.optsWithGlobals());
});
}
async function runMcpStream(tool, args, globalOpts) {
/**
* Shared JSON-RPC 2.0 MCP client used by both stream and non-stream `mcp call`.
*
* Protocol:
* 1. POST /api/mcp/stream with initialize → get Mcp-Session-Id header
* 2. POST /api/mcp/stream with tools/call + Mcp-Session-Id header
*
* When `stream` is true, writes SSE data chunks to stdout as they arrive.
* When `stream` is false, returns the parsed JSON-RPC result.
*
* Returns the exit code (0 = success, non-zero = failure).
*/
async function mcpJsonRpcCall(tool, args, { stream = false, globalOpts = {} } = {}) {
const baseUrl = globalOpts.baseUrl ?? "http://localhost:20128";
const apiKey = globalOpts.apiKey ?? "";
const res = await fetch(`${baseUrl}/api/mcp/stream`, {
const streamUrl = `${baseUrl}/api/mcp/stream`;
const hdrs = {
"Content-Type": "application/json",
Accept: stream ? "text/event-stream" : "application/json",
...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),
};
// Step 1 — initialize
const initRes = await fetch(streamUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),
},
body: JSON.stringify({ name: tool, arguments: args }),
headers: hdrs,
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "initialize",
params: {
protocolVersion: "2024-11-05",
capabilities: {},
clientInfo: { name: "omniroute-cli", version: "1.0" },
},
}),
});
if (!res.ok) {
process.stderr.write(`HTTP ${res.status}\n`);
process.exit(1);
if (!initRes.ok) {
const text = await initRes.text().catch(() => "");
process.stderr.write(`MCP initialize failed: HTTP ${initRes.status}${text ? `${text}` : ""}\n`);
return 1;
}
const reader = res.body.getReader();
const sessionId = initRes.headers.get("mcp-session-id");
if (!sessionId) {
process.stderr.write("MCP initialize failed: no Mcp-Session-Id in response\n");
return 1;
}
// Step 2 — tools/call
const callHeaders = {
...hdrs,
"mcp-session-id": sessionId,
};
const callRes = await fetch(streamUrl, {
method: "POST",
headers: callHeaders,
body: JSON.stringify({
jsonrpc: "2.0",
id: 2,
method: "tools/call",
params: { name: tool, arguments: args },
}),
});
if (!callRes.ok) {
const text = await callRes.text().catch(() => "");
process.stderr.write(`MCP call failed: HTTP ${callRes.status}${text ? `${text}` : ""}\n`);
return 1;
}
if (stream) {
return readMcpSseStream(callRes.body);
}
// Non-stream: parse JSON-RPC response
const data = await callRes.json();
if (data.error) {
process.stderr.write(`MCP error: ${data.error.message || JSON.stringify(data.error)}\n`);
return 1;
}
// Print the result content
const content = data.result?.content;
if (content) {
for (const item of content) {
if (item.type === "text") {
process.stdout.write(item.text + "\n");
} else if (item.type === "resource") {
process.stdout.write(JSON.stringify(item.resource) + "\n");
} else {
process.stdout.write(JSON.stringify(item) + "\n");
}
}
} else {
process.stdout.write(JSON.stringify(data.result, null, 2) + "\n");
}
return 0;
}
async function readMcpSseStream(body) {
if (!body) return 1;
const reader = body.getReader();
const dec = new TextDecoder();
let buf = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
buf += dec.decode(value, { stream: true });
const lines = buf.split("\n");
buf = lines.pop() ?? "";
for (const line of lines) {
if (line.startsWith("data: ")) {
const raw = line.slice(6).trim();
if (raw && raw !== "[DONE]") process.stdout.write(raw + "\n");
}
}
const lines = buf.split("\n");
for (const line of lines) {
if (line.startsWith("data: ")) {
const raw = line.slice(6).trim();
if (raw && raw !== "[DONE]") process.stdout.write(raw + "\n");
}
}
return 0;
}
export async function runMcpCallCommand(tool, args, opts = {}, globalOpts = {}) {
return mcpJsonRpcCall(tool, args, { stream: opts.stream, globalOpts });
}
export async function runMcpStatusCommand(opts = {}) {
@@ -233,7 +238,8 @@ export async function runMcpStatusCommand(opts = {}) {
}
const transport = status.transport || "stdio";
console.log(status.running ? t("mcp.running", { transport }) : t("mcp.stopped"));
const online = status.online ?? status.running;
console.log(online ? t("mcp.running", { transport }) : t("mcp.stopped"));
if (status.toolsCount !== undefined) console.log(` Tools: ${status.toolsCount}`);
if (status.scopes?.length) {
console.log(" Scopes:");

View File

@@ -258,8 +258,7 @@ async function runDeviceFlow(def, opts) {
process.stdout.write(`\nAuthorization URL not available\n\n`);
}
if (opts.browser !== false && verificationUri)
await openBrowser(verificationUri);
if (opts.browser !== false && verificationUri) await openBrowser(verificationUri);
process.stderr.write("Waiting for device authorization...\n");
const deadline = Date.now() + (opts.timeout ?? 300000);
const intervalMs = (start.intervalMs ?? start.interval ?? 5) * 1000;
@@ -320,7 +319,18 @@ export async function runOAuthStatus(opts, cmd) {
process.exit(1);
}
const data = await res.json();
const connections = (data.connections ?? data.providers ?? data.items ?? data).filter(
const payload = data?.connections ?? data?.providers ?? data?.items ?? data;
// #11236 (bug 5 residual): a 200 whose body is out of contract (no
// connections/providers/items array — e.g. `{"status":"ok"}`) used to fall
// through to `.filter` on a non-array and crash with a bare TypeError plus a
// libuv teardown assertion on Windows. Coerce to an empty list with a
// sanitized one-line warning instead of dumping a stack trace.
if (!Array.isArray(payload)) {
process.stderr.write(
"Warning: unexpected response shape from /api/providers; showing no connections.\n"
);
}
const connections = (Array.isArray(payload) ? payload : []).filter(
(c) => c.authType === "oauth" || c.authType === "oauth2"
);
emit(connections, globalOpts, connectionSchema);

View File

@@ -1,4 +1,5 @@
import { apiFetch } from "../api.mjs";
import { mcpCallTool } from "../mcpClient.mjs";
import { emit } from "../output.mjs";
import { t } from "../i18n.mjs";
@@ -8,15 +9,7 @@ function fmtTs(v) {
}
async function mcpCall(name, args) {
const res = await apiFetch("/api/mcp/tools/call", {
method: "POST",
body: { name, arguments: args },
});
if (!res.ok) {
process.stderr.write(`MCP error: ${res.status}\n`);
process.exit(1);
}
return res.json();
return mcpCallTool(name, args);
}
const proxySchema = [

View File

@@ -1,6 +1,7 @@
import { createInterface } from "node:readline";
import { Argument } from "commander";
import { apiFetch } from "../api.mjs";
import { mcpCallTool } from "../mcpClient.mjs";
import { emit } from "../output.mjs";
import { t } from "../i18n.mjs";
@@ -166,14 +167,7 @@ export function registerResilience(program) {
])
)
.action(async (name, opts, cmd) => {
const res = await apiFetch("/api/mcp/tools/call", {
method: "POST",
body: { name: "omniroute_set_resilience_profile", arguments: { profile: name } },
});
if (!res.ok) {
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
await mcpCallTool("omniroute_set_resilience_profile", { profile: name });
process.stdout.write(`Profile: ${name}\n`);
});

View File

@@ -1,7 +1,7 @@
import { spawn } from "node:child_process";
import { existsSync, readFileSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { fileURLToPath, pathToFileURL } from "node:url";
import { platform, totalmem } from "node:os";
import { t } from "../i18n.mjs";
import { writePidFile, cleanupPidFile, waitForServer } from "../utils/pid.mjs";
@@ -20,6 +20,7 @@ import {
buildNodeHeapArgs,
} from "../../../scripts/build/runtime-env.mjs";
import { resolveTlsOptions } from "../../../scripts/dev/tls-options.mjs";
import { startDetachedTray, validateTrayOptions } from "../tray/detachedTray.mjs";
const __dirname = dirname(fileURLToPath(import.meta.url));
const _pkg = JSON.parse(readFileSync(join(__dirname, "..", "..", "..", "package.json"), "utf8"));
@@ -42,7 +43,7 @@ function parsePort(value, fallback) {
}
export function registerServe(program) {
program
const command = program
.command("serve", { isDefault: true })
.description(t("serve.description"))
.option("--port <port>", t("serve.port"))
@@ -51,7 +52,7 @@ export function registerServe(program) {
.option("--log", t("serve.log"))
.option("--no-recovery", t("serve.no_recovery"))
.option("--max-restarts <n>", t("serve.max_restarts"), parseInt, 2)
.option("--tray", t("serve.tray") || "Show system tray icon (desktop only)")
.option("--tray", t("serve.tray") || "Start in the system tray (desktop only)")
.option("--no-tray", t("serve.no_tray") || "Disable system tray icon")
.option(
"--tls-cert <path>",
@@ -66,6 +67,9 @@ export function registerServe(program) {
.action(async (opts) => {
await runServe(opts);
});
command.addOption(command.createOption("--tray-worker").hideHelp());
command.addOption(command.createOption("--tray-ready-port <port>").hideHelp());
command.addOption(command.createOption("--tray-ready-token <token>").hideHelp());
}
/** Once-per-process guard so the Android/Termux cache hint is not spammed. */
@@ -95,6 +99,32 @@ export function resetInstrumentationFailureHintForTests() {
export async function runServe(opts = {}) {
const startedAt = performance.now();
const trayOptionError = validateTrayOptions(opts);
if (trayOptionError) throw new Error(trayOptionError);
if (opts.tray === true && opts.trayWorker !== true) {
const port = parsePort(opts.port ?? process.env.PORT ?? "20128", 20128);
const tlsCert = opts.tlsCert ?? process.env.OMNIROUTE_TLS_CERT;
const tlsKey = opts.tlsKey ?? process.env.OMNIROUTE_TLS_KEY;
urlScheme = resolveTlsOptions({
...process.env,
...(tlsCert ? { OMNIROUTE_TLS_CERT: tlsCert } : {}),
...(tlsKey ? { OMNIROUTE_TLS_KEY: tlsKey } : {}),
})
? "https"
: "http";
const result = await startDetachedTray({
cliPath: join(ROOT, "bin", "omniroute.mjs"),
port,
maxRestarts: opts.maxRestarts ?? 2,
tlsCert,
tlsKey,
});
console.log(`\x1b[32m✔ OmniRoute tray started in background\x1b[0m`);
console.log(` \x1b[1mDashboard:\x1b[0m ${urlScheme}://localhost:${port}`);
return result;
}
// Same prep as bin/omniroute.mjs — keep it here so a direct `runServe()` call
// (tests / programmatic) still gets a writable Next.js cache dir before spawn.
ensureAndroidCacheDir({ env: process.env });
@@ -264,7 +294,8 @@ export async function runServe(opts = {}) {
opts.log === true,
opts.maxRestarts ?? 2,
startedAt,
useTray
useTray,
{ trayReadyPort: opts.trayReadyPort, trayReadyToken: opts.trayReadyToken }
);
}
@@ -377,9 +408,11 @@ async function runWithSupervisor(
showLog,
maxRestarts,
startedAt,
useTray = false
useTray = false,
{ trayReadyPort, trayReadyToken } = {}
) {
if (showLog) process.env.OMNIROUTE_SHOW_LOG = "1";
writePidFile("supervisor", process.pid);
const supervisor = new ServerSupervisor({
serverPath: serverJs,
@@ -390,7 +423,7 @@ async function runWithSupervisor(
if (detectMitmCrash(crashLog)) {
try {
const PROJECT_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
const { updateSettings } = await import(`${PROJECT_ROOT}/src/lib/db/settings.ts`);
const { updateSettings } = await import(pathToFileURL(join(PROJECT_ROOT, "src/lib/db/settings.ts")).href);
updateSettings({ mitmEnabled: false });
} catch {}
return "disable-mitm-and-retry";
@@ -403,17 +436,38 @@ async function runWithSupervisor(
process.on("SIGINT", () => {
killTrayIfActive();
cleanupPidFile("supervisor");
supervisor.stop();
});
process.on("SIGTERM", () => {
killTrayIfActive();
cleanupPidFile("supervisor");
supervisor.stop();
});
if (!showLog) {
waitForServer(dashboardPort, 60000).then(async (up) => {
if (up) {
if (useTray) await maybeStartTray(dashboardPort, apiPort, supervisor);
if (useTray) {
const trayReady = await maybeStartTray(dashboardPort, apiPort, supervisor);
if (!trayReady) {
cleanupPidFile("supervisor");
supervisor.stop();
process.exitCode = 1;
return;
}
if (trayReadyPort && trayReadyToken) {
const { notifyTrayReady } = await import("../tray/detachedTray.mjs");
try {
await notifyTrayReady(parsePort(trayReadyPort, 0), trayReadyToken);
} catch {
cleanupPidFile("supervisor");
supervisor.stop();
process.exitCode = 1;
return;
}
}
}
onReady(dashboardPort, apiPort, noOpen, startedAt);
} else {
reportReadinessTimeout(dashboardPort, supervisor);
@@ -460,29 +514,30 @@ function killTrayIfActive() {
async function maybeStartTray(port, apiPort, supervisor) {
try {
const { initTray, isTraySupported } = await import("../tray/index.mjs");
if (!isTraySupported()) return;
if (!isTraySupported()) return false;
const { default: open } = await import("open").catch(() => ({ default: null }));
const dashboardUrl = `${urlScheme}://localhost:${port}`;
const tray = await initTray({
port,
onQuit: () => {
killTrayIfActive();
cleanupPidFile("supervisor");
supervisor.stop();
},
onOpenDashboard: () => open?.(dashboardUrl),
onShowLogs: () => {
// In-place: open logs stream (best-effort)
process.stdout.write(`[omniroute][tray] Logs at: ${dashboardUrl}/logs\n`);
},
onShowLogs: () => open?.(`${dashboardUrl}/dashboard/logs`),
});
if (tray) {
const { killTray } = await import("../tray/index.mjs");
_killTray = killTray;
return true;
}
return false;
} catch (err) {
// tray is optional — do not fail the server, but surface why it failed so
// "--tray shows nothing" is diagnosable instead of silent (#4605).
process.stderr.write(`[omniroute][tray] failed to start: ${err?.message ?? String(err)}\n`);
return false;
}
}

View File

@@ -1,4 +1,4 @@
import { fileURLToPath } from "node:url";
import { fileURLToPath, pathToFileURL } from "node:url";
import { dirname, resolve } from "node:path";
import { createPrompt, printHeading, printInfo, printSuccess } from "../io.mjs";
import { openOmniRouteDb } from "../sqlite.mjs";
@@ -16,7 +16,7 @@ import { t } from "../i18n.mjs";
const PROJECT_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
async function getListCliTools() {
const { listCliTools } = await import(`${PROJECT_ROOT}/src/shared/constants/cliTools.ts`);
const { listCliTools } = await import(pathToFileURL(resolve(PROJECT_ROOT, "src/shared/constants/cliTools.ts")).href);
return listCliTools;
}

View File

@@ -1,5 +1,6 @@
import { readFileSync } from "node:fs";
import { apiFetch } from "../api.mjs";
import { mcpCallTool } from "../mcpClient.mjs";
import { emit } from "../output.mjs";
import { t } from "../i18n.mjs";
@@ -106,14 +107,7 @@ export async function runSkillsInstall(opts, cmd) {
}
export async function runSkillsEnable(id, opts, cmd) {
const res = await apiFetch("/api/mcp/tools/call", {
method: "POST",
body: { name: "omniroute_skills_enable", arguments: { skillId: id, enabled: true } },
});
if (!res.ok) {
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
await mcpCallTool("omniroute_skills_enable", { skillId: id, enabled: true });
process.stdout.write(`Enabled: ${id}\n`);
}
@@ -122,14 +116,7 @@ export async function runSkillsDisable(id, opts, cmd) {
const ok = await confirm(`Disable ${id}?`);
if (!ok) return;
}
const res = await apiFetch("/api/mcp/tools/call", {
method: "POST",
body: { name: "omniroute_skills_enable", arguments: { skillId: id, enabled: false } },
});
if (!res.ok) {
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
await mcpCallTool("omniroute_skills_enable", { skillId: id, enabled: false });
process.stdout.write(`Disabled: ${id}\n`);
}
@@ -153,16 +140,11 @@ export async function runSkillsExecute(id, opts, cmd) {
: opts.inputFile
? JSON.parse(readFileSync(opts.inputFile, "utf8"))
: {};
const res = await apiFetch("/api/mcp/tools/call", {
method: "POST",
body: { name: "omniroute_skills_execute", arguments: { skillId: id, input } },
timeout: opts.timeout ?? 30000,
});
if (!res.ok) {
process.stderr.write(`Error: ${res.status}\n`);
process.exit(1);
}
const data = await res.json();
const data = await mcpCallTool(
"omniroute_skills_execute",
{ skillId: id, input },
{ timeout: opts.timeout ?? 30000 },
);
emit(data, globalOpts);
}

View File

@@ -254,7 +254,7 @@
"log": "Show server logs inline",
"no_recovery": "Disable auto-restart on crash (debugging mode)",
"max_restarts": "Max crash restarts within 30s before giving up (default: 2)",
"tray": "Show system tray icon (desktop only, opt-in)",
"tray": "Start in the system tray (desktop only, opt-in)",
"no_tray": "Disable system tray icon",
"tls_cert": "Path to a TLS certificate (PEM) to serve HTTPS (also OMNIROUTE_TLS_CERT)",
"tls_key": "Path to the TLS private key (PEM) to serve HTTPS (also OMNIROUTE_TLS_KEY)"

View File

@@ -26,7 +26,8 @@
"testFailed": "Teste do provedor falhou: {error}",
"loginEnabled": "Login: habilitado (senha atualizada)",
"loginDisabled": "Login: desabilitado",
"providerInfo": "Provedor: {info}"
"providerInfo": "Provedor: {info}",
"opencode": "Instala e configura o plugin @omniroute/opencode-plugin incluído para o OpenCode"
},
"doctor": {
"title": "OmniRoute Doctor",
@@ -254,7 +255,9 @@
"no_recovery": "Desabilitar reinício automático em crash (modo debug)",
"max_restarts": "Máximo de reinícios em 30s antes de desistir (padrão: 2)",
"tray": "Mostrar ícone na bandeja do sistema (apenas desktop, opt-in)",
"no_tray": "Desabilitar ícone na bandeja do sistema"
"no_tray": "Desabilitar ícone na bandeja do sistema",
"tls_cert": "Caminho para um certificado TLS (PEM) para servir HTTPS (também OMNIROUTE_TLS_CERT)",
"tls_key": "Caminho para a chave privada TLS (PEM) para servir HTTPS (também OMNIROUTE_TLS_KEY)"
},
"backup": {
"title": "Backup",

127
bin/cli/mcpClient.mjs Normal file
View File

@@ -0,0 +1,127 @@
/**
* Shared MCP JSON-RPC client for CLI commands.
*
* The server exposes MCP through /api/mcp/stream (Streamable HTTP transport).
* Calling a tool requires:
* 1. POST initialize → get Mcp-Session-Id response header
* 2. POST tools/call with that session header
*
* Older CLI paths POSTed { name, arguments } to /api/mcp/tools/call, which is
* not a registered route, so every MCP-backed command was broken.
*
* These functions route through apiFetch so CLI auth, remote contexts and
* timeouts are handled the same way as every other management API call.
*/
import { apiFetch } from "./api.mjs";
function mcpError(message, status) {
const err = new Error(message);
if (status) err.status = status;
return err;
}
async function callMcpEndpoint(payload, { timeout, stream }) {
const res = await apiFetch("/api/mcp/stream", {
method: "POST",
body: payload,
timeout,
acceptNotOk: true,
headers: stream ? { Accept: "text/event-stream" } : {},
});
if (!res.ok) {
const text = await res.text().catch(() => "");
throw mcpError(
`${payload.method} ${payload.id}: HTTP ${res.status}${text ? `${text}` : ""}`,
res.status,
);
}
return res;
}
/**
* Call an MCP tool over /api/mcp/stream.
*
* Non-stream: returns the JSON-RPC result payload.
* Stream: writes SSE `data:` chunks to stdout and returns null on success.
*/
export async function mcpCallTool(name, args = {}, options = {}) {
const { timeout, scope } = options;
const scopeHeader = scope?.length ? { "X-MCP-Scopes": scope.join(",") } : {};
const initRes = await callMcpEndpoint(
{
jsonrpc: "2.0",
id: 1,
method: "initialize",
params: {
protocolVersion: "2024-11-05",
capabilities: {},
clientInfo: { name: "omniroute-cli", version: "1.0" },
},
},
{ timeout, stream: options.stream },
);
const sessionId = initRes.headers.get("mcp-session-id");
if (!sessionId) {
throw mcpError("MCP initialize failed: no Mcp-Session-Id in response", 500);
}
const callRes = await callMcpEndpoint(
{
jsonrpc: "2.0",
id: 2,
method: "tools/call",
params: { name, arguments: args },
},
{ timeout, stream: options.stream },
);
if (options.stream) {
return consumeSse(callRes.body, options.onChunk);
}
const data = await callRes.json();
if (data.error) {
const err = mcpError(`MCP error: ${data.error.message || JSON.stringify(data.error)}`);
err.code = data.error.code;
throw err;
}
if (data.result?.isError) {
const msg = data.result?.content?.[0]?.text || "unknown tool error";
throw mcpError(`MCP error: ${msg}`, 500);
}
return data.result;
}
async function consumeSse(body, onChunk) {
if (!body) throw mcpError("MCP stream returned no body", 500);
const reader = body.getReader();
const decoder = new TextDecoder();
let buf = "";
const flushLines = () => {
let idx;
while ((idx = buf.indexOf("\n")) >= 0) {
const line = buf.slice(0, idx);
buf = buf.slice(idx + 1);
if (line.startsWith("data: ")) {
const raw = line.slice(6).trim();
if (raw && raw !== "[DONE]") (onChunk ?? writeStdout)(raw);
}
}
};
while (true) {
const { done, value } = await reader.read();
if (done) break;
buf += decoder.decode(value, { stream: true });
flushLines();
}
buf += decoder.decode();
flushLines();
return null;
}
function writeStdout(raw) {
process.stdout.write(raw + "\n");
}

View File

@@ -10,6 +10,10 @@ const PROVIDER_TEST_CONFIGS = {
format: "openai",
baseUrl: "https://openrouter.ai/api/v1",
model: "openai/gpt-4o-mini",
// #11226: /models is public on OpenRouter (200 with any or no key) — probe the
// authenticated key-info endpoint instead so a bad key fails the test here
// instead of on the first real chat request.
keyCheckPath: "/auth/key",
},
groq: {
format: "openai",
@@ -101,13 +105,19 @@ async function testOpenAILikeProvider(input, config) {
"Content-Type": "application/json",
};
const modelsRes = await fetchWithTimeout(joinUrl(config.baseUrl, "/models"), {
method: "GET",
headers,
});
// Providers whose /models endpoint is public (e.g. OpenRouter) declare a
// keyCheckPath pointing at an authenticated endpoint so the probe actually
// exercises the key instead of the public catalog.
const probeRes = await fetchWithTimeout(
joinUrl(config.baseUrl, config.keyCheckPath || "/models"),
{
method: "GET",
headers,
}
);
if (modelsRes.ok || modelsRes.status === 401 || modelsRes.status === 403) {
return classifyResponse(modelsRes);
if (probeRes.ok || probeRes.status === 401 || probeRes.status === 403) {
return classifyResponse(probeRes);
}
const chatRes = await fetchWithTimeout(joinUrl(config.baseUrl, "/chat/completions"), {

View File

@@ -1,9 +1,14 @@
import { fileURLToPath } from "node:url";
import { fileURLToPath, pathToFileURL } from "node:url";
import { dirname, resolve } from "node:path";
import { apiFetch, isServerUp } from "./api.mjs";
const PROJECT_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
// Dynamic `import()` resolves its specifier as a URL, not as a filesystem path.
// On Windows an absolute path starts with a drive letter, which the ESM loader
// reads as the unsupported URL scheme `e:` and rejects. Pass a file:// URL.
const projectFileUrl = (relPath) => pathToFileURL(resolve(PROJECT_ROOT, relPath)).href;
export class ServerOfflineError extends Error {
constructor(message = "Server is offline and operation requires HTTP runtime") {
super(message);
@@ -22,8 +27,8 @@ function makeHttpContext(opts) {
async function importDbModules() {
const [combos, recovery] = await Promise.all([
import(`${PROJECT_ROOT}/src/lib/db/combos.ts`),
import(`${PROJECT_ROOT}/src/lib/db/recovery.ts`),
import(projectFileUrl("src/lib/db/combos.ts")),
import(projectFileUrl("src/lib/db/recovery.ts")),
]);
return { combos, recovery };
}

View File

@@ -6,7 +6,9 @@ import { pathToFileURL } from "node:url";
import { validateBinaryMagic, platformBinaryLabel } from "./magicBytes.mjs";
const RUNTIME_DIR = join(homedir(), ".omniroute", "runtime");
const BETTER_SQLITE3_VERSION = "better-sqlite3@^12.10.1";
// Exported so the packaging coherence guard (tests/unit/pack-boot-runtime-paths.test.ts)
// can assert this stays on the same major as optionalDependencies.better-sqlite3 (#11242).
export const BETTER_SQLITE3_VERSION = "better-sqlite3@^13.0.2";
let resolvedCached = null;

View File

@@ -276,6 +276,10 @@ function isAgentSelfMac() {
}
}
function isDetachedTrayWorker() {
return process.argv.includes("--tray-worker");
}
function enableMac() {
const plistDir = join(homedir(), "Library", "LaunchAgents");
mkdirSync(plistDir, { recursive: true });
@@ -300,7 +304,7 @@ function enableMac() {
// If we're already the running agent, launchctl load/unload would SIGTERM us.
// The plist is updated on disk and launchd already has us loaded under our own
// PID — nothing more to do for the current session.
if (isAgentSelfMac()) return existsSync(plistPath);
if (isAgentSelfMac() || isDetachedTrayWorker()) return existsSync(plistPath);
try {
execSync("launchctl load -w " + JSON.stringify(plistPath), { stdio: "ignore" });
} catch {}
@@ -313,7 +317,7 @@ function disableMac() {
// `launchctl unload` sends SIGTERM and a user clicking "Disable Autostart"
// from the tray would lose the tray icon instead of just flipping the label.
// Removing the plist file is enough to stop the agent at the next login.
if (!isAgentSelfMac()) {
if (!isAgentSelfMac() && !isDetachedTrayWorker()) {
try {
execSync("launchctl unload -w " + JSON.stringify(plistPath), { stdio: "ignore" });
} catch {}

View File

@@ -0,0 +1,176 @@
import { execFileSync, spawn } from "node:child_process";
import { randomBytes, timingSafeEqual } from "node:crypto";
import { createServer, connect } from "node:net";
/** Builds arguments for the hidden process that owns the server and tray. */
export function buildTrayWorkerArgs({ port, maxRestarts, readyPort, readyToken, tlsCert, tlsKey }) {
const args = [
"serve",
"--tray",
"--tray-worker",
"--no-open",
"--port",
String(port),
"--max-restarts",
String(maxRestarts),
"--tray-ready-port",
String(readyPort),
"--tray-ready-token",
readyToken,
];
if (tlsCert) args.push("--tls-cert", tlsCert);
if (tlsKey) args.push("--tls-key", tlsKey);
return args;
}
/** Builds the platform command that starts the hidden tray worker. */
export function buildTrayLaunch({ platform, execPath, cliPath, workerArgs, label }) {
if (platform === "darwin") {
return {
command: "launchctl",
args: ["submit", "-l", label, "--", execPath, cliPath, ...workerArgs],
options: { stdio: "ignore" },
};
}
return {
command: execPath,
args: [cliPath, ...workerArgs],
options: { detached: true, stdio: "ignore", windowsHide: true },
};
}
/** Returns an error for command modes that conflict with detached tray mode. */
export function validateTrayOptions(opts) {
if (opts.trayWorker && (!opts.trayReadyPort || !opts.trayReadyToken)) {
return "tray worker requires readiness credentials";
}
if (!opts.tray || opts.trayWorker) return null;
if (opts.daemon) return "--tray cannot use --daemon";
if (opts.log) return "--tray cannot use --log";
if (opts.noRecovery || opts.recovery === false) return "--tray cannot use --no-recovery";
return null;
}
/** Creates a token-protected loopback server for tray worker readiness. */
export async function createTrayReadinessServer(token) {
let markReady;
const ready = new Promise((resolve) => {
markReady = resolve;
});
const expected = Buffer.from(token);
const server = createServer((socket) => {
let data = "";
socket.setEncoding("utf8");
socket.on("data", (chunk) => {
data += chunk;
if (data.length > 256) socket.destroy();
});
socket.on("end", () => {
const received = Buffer.from(data);
if (received.length !== expected.length || !timingSafeEqual(received, expected)) {
socket.end("ERROR");
return;
}
socket.end("READY");
markReady();
});
});
await new Promise((resolve, reject) => {
server.once("error", reject);
server.listen(0, "127.0.0.1", resolve);
});
const address = server.address();
return {
port: address.port,
wait(timeoutMs) {
return new Promise((resolve, reject) => {
const timer = setTimeout(
() => reject(new Error("Tray worker did not become ready")),
timeoutMs
);
ready.then(() => {
clearTimeout(timer);
resolve();
});
});
},
close() {
server.close();
},
};
}
/** Notifies the parent process that the server and tray are ready. */
export async function notifyTrayReady(port, token) {
await new Promise((resolve, reject) => {
const socket = connect({ host: "127.0.0.1", port }, () => socket.end(token));
let reply = "";
socket.setEncoding("utf8");
socket.on("data", (chunk) => {
reply += chunk;
});
socket.on("end", () => {
if (reply === "READY") resolve();
else reject(new Error("Tray readiness token was rejected"));
});
socket.on("error", reject);
});
}
/** Starts a detached tray worker and waits until its server and tray are ready. */
export async function startDetachedTray(
{ cliPath, port, maxRestarts, tlsCert, tlsKey, timeoutMs = 60000 },
{ platform = process.platform, spawnProcess = spawn } = {}
) {
const token = randomBytes(32).toString("hex");
const readiness = await createTrayReadinessServer(token);
const label = `com.omniroute.tray.${process.pid}.${Date.now()}`;
const workerArgs = buildTrayWorkerArgs({
port,
maxRestarts,
readyPort: readiness.port,
readyToken: token,
tlsCert,
tlsKey,
});
const launch = buildTrayLaunch({
platform,
execPath: process.execPath,
cliPath,
workerArgs,
label,
});
const child = spawnProcess(launch.command, launch.args, launch.options);
const spawnFailure = new Promise((_, reject) => {
child.once("error", reject);
child.once("exit", (code) => {
if (platform !== "darwin" || code !== 0) {
reject(new Error(`Tray worker exited before readiness with code ${code ?? "unknown"}`));
}
});
});
if (platform !== "darwin") child.unref?.();
try {
await Promise.race([readiness.wait(timeoutMs), spawnFailure]);
return { platform, pid: child.pid, label: platform === "darwin" ? label : null };
} catch (err) {
if (platform === "darwin") {
try {
execFileSync("launchctl", ["bootout", `gui/${process.getuid()}/${label}`], {
stdio: "ignore",
});
} catch {}
} else if (platform === "win32" && child.pid) {
try {
execFileSync("taskkill", ["/PID", String(child.pid), "/T", "/F"], { stdio: "ignore" });
} catch {}
} else if (child.pid) {
try {
process.kill(child.pid, "SIGTERM");
} catch {}
}
throw err;
} finally {
readiness.close();
}
}

View File

@@ -97,9 +97,7 @@ export async function initSystrayUnix(
}
});
tray.ready().catch((err) => {
process.stderr.write(`[omniroute][tray] systray2 failed: ${err?.message ?? String(err)}\n`);
});
await tray.ready();
return tray;
}

View File

@@ -0,0 +1 @@
- **feat(audio):** proxy native ElevenLabs voices, text-to-speech, and speech-to-text HTTP routes through stored OmniRoute credentials, preserving query strings, multipart uploads, binary responses, and upstream errors (#10556).

View File

@@ -0,0 +1 @@
- Added Google AI Studio Gemini batch text-to-speech support through `POST /v1/audio/speech`.

View File

@@ -0,0 +1,3 @@
- Run synchronous RTK and Caveman request compression in a bounded worker-thread pool, keeping
large `/v1/responses` compression heaps outside the HTTP isolate while preserving strict
fail-open behavior and per-engine telemetry.

View File

@@ -0,0 +1 @@
- **feat(combo):** the shared per-request combo attempt budget is now operator-configurable via `maxGlobalAttempts` (combo config / `comboDefaults` cascade), instead of the hardcoded 30. Lower it to fail fast on a dead target pool, raise it for large combos; clamped to `[1, 200]` so an unbounded budget can never cause runaway background requests ([#11134](https://github.com/diegosouzapw/OmniRoute/issues/11134))

View File

@@ -0,0 +1 @@
- **feat(providers):** allow overriding the rate-limit queue wait timeout (`maxWaitMs`) per connection, alongside the existing `rpm`/`tpm`/`tpd`/`minTime`/`maxConcurrent` overrides — a single slow provider no longer has to lower the global wait budget for every other provider (#11251)

View File

@@ -0,0 +1 @@
- **feat(dashboard):** replace the hard Home → onboarding redirect with a dismissable first-run readiness card so returning users can stay on Home while new users still get a clear 4-step path ([#11282](https://github.com/diegosouzapw/OmniRoute/pull/11282))

View File

@@ -0,0 +1 @@
- **feat(dashboard):** lead Traffic Inspector with a purpose-first header that separates "what happened" from "how it happened", so beginners can read request outcomes without drowning in protocol detail ([#11283](https://github.com/diegosouzapw/OmniRoute/pull/11283))

View File

@@ -0,0 +1 @@
- **feat(dashboard):** add an Essentials sidebar preset that shows only the beginner core path (Home → Endpoints → API Keys → Providers → Health → Settings) while keeping Advanced tools reachable via Command Palette search ([#11286](https://github.com/diegosouzapw/OmniRoute/pull/11286))

View File

@@ -0,0 +1 @@
- feat(services): show sanitized CLIProxyAPI account health from its authenticated management API without exposing credentials, file paths, or raw account metadata (#6342)

View File

@@ -0,0 +1 @@
- **feat(catalog):** surface runtime-learned `reasoning_effort` tiers in `/v1/models` `capabilities.effort_tiers` (learned set replaces synced metadata when present), map them to OpenCode `ModelV2.variants` in the OmniRoute plugin, and align dispatch `-<tier>` suffix validation to the effective (learned ?? synced) set — so the UI offers exactly the tiers the upstream accepts (e.g. `{low, high, max}` for `oc/x-preview-f-free`) and each advertised variant completes. Excludes codex/glm/kimi, which keep their own dedicated `-{effort}` suffix mechanism and never gain `effort_tiers` from this path (related to #7694, builds on #11232)

View File

@@ -0,0 +1 @@
- **feat(cli):** run `omniroute serve --tray` as a detached desktop process after server and tray readiness, with graphical login auto-start support.

View File

@@ -0,0 +1 @@
- **fix(build):** stop the native `better-sqlite3` addon from loading during the Next.js production build (#10060). Its `Statement` destructor aborts with `SIGABRT` when a build worker thread exits (assertion in `node::RemoveEnvironmentCleanupHook`, `env == nullptr`), which can leave the build with no standalone bundle. Every DB entry point now keys off a reliable `OMNIROUTE_BUILDING=1` signal (set by `build-next-isolated.mjs` and inherited by every spawned build worker, because Next.js workers sometimes drop `NEXT_PHASE`): `getDbInstance()` returns a no-op SQLite stub during build, `driverFactory` skips the native driver and falls through to `node:sqlite`, and the `codegraph`/`kiro-import` lazy loaders fail closed. A build-time `better-sqlite3` alias to a stub (`next.config.mjs`, turbopack) backs this up without changing runtime behaviour (the real package is still `require()`d natively via `serverExternalPackages`). Also raises the default build heap 4096→6144 MB and caps Next build worker pools (`CIRCLE_NODE_TOTAL=8`) to avoid the many-core page-data-collection SIGSEGV, and adds `.gitattributes` (`*.sh text eol=lf`) so kernel-exec'd shell scripts never ship with CRLF shebangs. Deliberately does NOT downgrade the Node base image: per the maintainer's review on #10060, `release/v3.8.50` moved to `node:26-trixie-slim` through several considered commits, so the `OMNIROUTE_BUILDING` guard is re-derived against the current base rather than reverting the FROM line; the npm pin and binary-hide dance from the original PR are dropped because our build already rebuilds `better-sqlite3` deterministically via `node-gyp` and floats `npm@latest` for the CVE overlay.

View File

@@ -1 +0,0 @@
- fix(sse): mark gemini-3.5-flash as thinking-capable so reasoning_effort is no longer rejected with a spurious 400 (#10286)

View File

@@ -0,0 +1 @@
- **fix(github):** proactive credential health now verifies GitHub access tokens through the existing Copilot token exchange, marks only a confirmed `401 Unauthorized` as expired, and leaves rate limits, permission failures, upstream failures, and network errors routable ([#10352](https://github.com/diegosouzapw/OmniRoute/issues/10352)) — thanks @RaviTharuma

View File

@@ -0,0 +1 @@
- fix(oauth): stop treating the Kiro profile ARN as an account identity in `findKiroConnectionByIdentity()`, so a second Google/GitHub social login creates a new connection instead of overwriting the first — distinct Builder ID accounts share the same CodeWhisperer profile ARN, and the social token is not a JWT, so no e-mail was available to disambiguate them (#10815)

View File

@@ -0,0 +1 @@
- Document the conditional management authentication and 401/403 responses for `GET /api/openapi/spec`.

View File

@@ -0,0 +1 @@
- fix(sse): default single-target incompatible reasoning to drop for agentic replay — single-target requests to opaque reasoning targets now gracefully strip incompatible plaintext reasoning history instead of returning HTTP 400, matching combo default behavior while preserving operator and per-request overrides ([#10959](https://github.com/diegosouzapw/OmniRoute/issues/10959))

View File

@@ -0,0 +1 @@
- **fix(ollama):** Ollama Local models are no longer flattened to `chat` at sync time — the synced store persists every advertised capability and chat filtering moves to read time, so `/v1/embeddings` and `/v1/images/generations` stop rejecting models the daemon reports as capable ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271)) — thanks @yourspraveen

View File

@@ -0,0 +1 @@
- **fix(translator):** preserve omitted OpenCode `subagent.sessionID` values — optional default-less plain strings now use the Responses `null = omit` sentinel and are stripped before the client sees the tool call, so Codex/Responses no longer invent filler session IDs ([#11297](https://github.com/diegosouzapw/OmniRoute/pull/11297)) — thanks @ofonseca-pyming

View File

@@ -0,0 +1 @@
- **fix(db):** group model patterns escape regex metacharacters, so `gpt-4.1*` no longer matches `gpt-4o1-preview` and a pattern like `gpt-4(*` no longer throws `SyntaxError` out of the completion and `/v1/models` paths ([#11311](https://github.com/diegosouzapw/OmniRoute/pull/11311))

View File

@@ -0,0 +1 @@
- **fix(db):** the upstream proxy URL check judges the host by address instead of by spelling, so `http://[::ffff:169.254.169.254]`, `[::ffff:10.0.0.5]`, ULA/link-local and CGNAT targets are refused like their dotted equivalents ([#11319](https://github.com/diegosouzapw/OmniRoute/pull/11319))

View File

@@ -0,0 +1 @@
- **fix(i18n):** three `pt` strings had dropped their placeholders — the cache tile's subtitle repeated its own label instead of showing `{total}` — and a unit test now enforces placeholder parity with `en` across all locales ([#11325](https://github.com/diegosouzapw/OmniRoute/pull/11325))

View File

@@ -0,0 +1 @@
- **fix(kie):** map the remaining `google-imagen/*` KIE Market catalog ids (`nano-banana`, `nano-banana-pro`, `nano-banana-edit`) to their real, KIE-documented upstream `model` values — `#11225`'s fix only covered `nano-banana-2` ([#11326](https://github.com/diegosouzapw/OmniRoute/pull/11326)).

View File

@@ -0,0 +1 @@
- **fix(security):** `proxy-authorization` and `proxy-authenticate` are refused as upstream/custom headers, so a proxy credential is no longer forwarded to the model provider — the canonical denylist now matches the RFC 7230 §6.1 set the rest of the codebase already strips ([#11328](https://github.com/diegosouzapw/OmniRoute/pull/11328))

View File

@@ -0,0 +1 @@
- **fix(usage):** keep session/weekly/monthly quota windows in chronological order on every provider card. The order is now derived from the quota keys themselves instead of a provider whitelist, so Claude, MiniMax, Z.ai and Command Code stop rendering the two bars in opposite positions across sibling accounts ([#7764](https://github.com/diegosouzapw/OmniRoute/issues/7764))

View File

@@ -0,0 +1 @@
- Hardened the Codex app-server transport after the post-merge security review of #11205: approval prompts from the app-server (its own command/file/permission execution — not the harness tool passthrough) are now auto-denied by default, with opt-in auto-approval via `providerSpecificData.codexAppServerAutoApprove` / `OMNIROUTE_CODEX_APPSERVER_AUTO_APPROVE`; the default codex sandbox changed from `danger-full-access` to `workspace-write` (override per connection or env); env-sourced capability tokens are now only sent to env-sourced URLs or operator-local hosts (loopback/RFC1918/link-local/ULA/localhost/single-label LAN names/*.local/*.ts.net/*.internal), so a connection's providerSpecificData URL can no longer exfiltrate the operator's env token; and the `/readyz` health probe no longer follows redirects while carrying the bearer token.

View File

@@ -0,0 +1 @@
- fix(codex): prefer `max_context_window` over the `context_window` pricing tier as the usable input limit in discovery, and raise the static Codex OAuth catalog to the same usable window so the conservative discovery merge no longer caps live values at the 272K pricing tier

View File

@@ -0,0 +1 @@
- **fix(security):** harden three secret-leak paths surfaced by an audit of the error/log surface. (1) `upstreamErrorPassthrough` relays an upstream provider's 4xx body verbatim to Claude-Code-format clients (the capability-recovery contract needs the exact wording); it now refuses passthrough when the body actually carries a credential pattern (`Bearer`/`Basic` token, `sk-…`, or an `api_key`/`token`/`authorization`/`cookie`/`secret` assignment) so a provider that echoes the offending request can't relay a key to the client, falling back to the sanitized error path. The credential regex is bounded (ReDoS-safe, verified linear at 60k chars). (2) The OCR and moderations handlers no longer forward an upstream error body byte-for-byte; they run it through the (now exported) structure-preserving `redactSensitiveErrorText` first. (3) `protectPayloadForLog`'s sensitive-key set gains `cookie`/`storageState`/`runtimeKey`/`capability` so web-impersonation credentials (Meta AI `ecto_1_sess`, chatgpt-web `storageState`) that land in a request/response body field are redacted before the call-log artifact is written to disk. No behavior change for secret-free error bodies; the Claude Code verbatim-wording contract is preserved.

View File

@@ -0,0 +1 @@
- **docs(database):** align the SQLite cache guide with the 65,536 KiB runtime default, supported 11,000,000 KiB range, and live Settings application behavior ([#11018](https://github.com/diegosouzapw/OmniRoute/issues/11018))

View File

@@ -0,0 +1 @@
- **chore(lint):** ratchet `@typescript-eslint/no-unused-vars` scoped to `src/` + `open-sse/` + `tests/` (`args: "all"`, `_`-prefix escape hatch) and freeze the 1393 pre-existing violations via bulk suppressions — same pattern as the #7879 `toNumber` ratchet. New unused bindings now fail lint. ([#11247](https://github.com/diegosouzapw/OmniRoute/pull/11247))

View File

@@ -0,0 +1,3 @@
- **fix(deps):** prevent pnpm from auto-installing the unused `@lobehub/ui` peer subtree of
`@lobehub/icons`, keeping six unneeded packages with incompatible or unverifiable license
metadata out of production installs ([#11342](https://github.com/diegosouzapw/OmniRoute/pull/11342)).

View File

@@ -1,5 +1,9 @@
{
"_comment": "Allowlist anti-slopsquatting (check-deps.mjs). Toda dep nova exige adicao EXPLICITA aqui apos verificar que e legitima.",
"_justifications": {
"@testing-library/dom": "Peer dep obrigatoria de @testing-library/react v16 (adicionada no PR #11224); Refs #9985.",
"@testing-library/user-event": "Utilitario oficial do ecossistema testing-library para testes de UI (adicionada no PR #11224); Refs #9985."
},
"allowed": [
"@atjsh/llmlingua-2",
"@aws-sdk/client-bedrock-runtime",
@@ -20,8 +24,10 @@
"@stryker-mutator/tap-runner",
"@swc/helpers",
"@tailwindcss/postcss",
"@testing-library/dom",
"@testing-library/jest-dom",
"@testing-library/react",
"@testing-library/user-event",
"@toon-format/toon",
"@types/better-sqlite3",
"@types/bun",

File diff suppressed because it is too large Load Diff

View File

@@ -433,7 +433,7 @@
"src/shared/components/analytics/charts.tsx": 1346,
"src/shared/services/cliRuntime.ts": 1459,
"src/sse/handlers/chat.ts": 2493,
"src/sse/services/auth.ts": 3337,
"src/sse/services/auth.ts": 3344,
"_rebaseline_2026_08_23_11186_synced_inventory_routing": "PR #11186 (pacocartones) own growth: src/sse/services/auth.ts 3260->3337 (+77, loadAdvertisedModelsForSelfHostedConnections + the modelNotAdvertised candidate-filter predicate — pins chat routing to the connection whose synced inventory actually advertises the model, fixing spurious model-not-found on multi-host self-hosted setups; at the existing credential-selection chokepoint, not extractable without splitting the selection flow). Covered by tests/unit/chat-routing-synced-inventory-11089.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
"tests/unit/account-fallback-service.test.ts": 2044,
"tests/unit/provider-validation-specialty.test.ts": 3880,
@@ -451,7 +451,8 @@
"src/shared/components/ModelSelectModal.tsx": 1138,
"src/shared/constants/providers/apikey/gateways.ts": 1250
},
"src/app/(dashboard)/dashboard/providers/[id]/components/modals/AddApiKeyModal.tsx": 1082,
"src/app/(dashboard)/dashboard/providers/[id]/components/modals/AddApiKeyModal.tsx": 1173,
"_rebaseline_2026_08_23_11207_aws_polly_fields": "PR #11207 (rafacpti23, draft) own growth: AddApiKeyModal.tsx 1082->1173 (+91, AWS SigV4 credential fields for aws-polly — Access Key ID / Region / optional Session Token blocks with providerText i18n labels, at the existing per-provider form-section chokepoint; the file is the known god-modal with repeated dated rebaselines). Covered by tests/unit/dashboard/aws-polly-connection-modal-fields.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
"_rebaseline_2026_08_22_11156_enter_check_disabled": "PR #11156 (rqzbeh) own growth: AddApiKeyModal.tsx 1080->1082 (+2, Enter keydown handler now mirrors the isCheckDisabled condition — owner-requested post-merge polish from #11056; the rest of the diff is Prettier reflow). Covered by tests/unit/ui/add-api-key-modal-enter-key.test.tsx (jsdom render test, Enter dispatch assertions).",
"src/app/(dashboard)/dashboard/providers/[id]/hooks/useProviderConnections.ts": 1051,
"src/shared/components/ModelSelectModal.tsx": 1138,
@@ -463,14 +464,15 @@
"src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts": 1014,
"open-sse/config/imageRegistry.ts": 1034,
"src/sse/handlers/chatHelpers.ts": 1019,
"src/shared/middleware/chatBodyAdmission.ts": 1009,
"src/shared/middleware/chatBodyAdmission.ts": 1118,
"_rebaseline_2026_08_22_11020_sigterm_drain": "PR #11020 (RaviTharuma) own growth: chatBodyAdmission.ts 1005->1009 (+4, heavyweight admission leases now increment the SIGTERM drain counter and releaseChatAdmissionWhenDone holds it for the SSE lifetime — closes #11015; +4 are the lease/drain wiring lines at the existing admission chokepoint). Covered by tests/unit/chat-body-admission.test.ts heavyweight-lease cases. Owner pre-authorized baseline bumps 2026-08-22.",
"_rebaseline_2026_08_20_10668_tabitoken_gateway": "#10668 (yawar-aquil) own catalog growth: src/shared/constants/providers/apikey/gateways.ts 1268->1283 (+15, entirely this PR diff -- one new tabitoken gateway entry, data lines only; base moved from 1255 to 1268 via other merges since the PR forked). Not combination drift: reproducible on the PR branch alone, so the WS5.5 release-captain rule does not apply. Extraction is not available -- the file is pure data (own header: \"Pure data; merged by apikey/index.ts via spread\") and already split into 6 family files under apikey/. Same precedent as _rebaseline_2026_08_14_imagetotext_servicekinds (#10275/#10291, gateways.ts 1250->1255, data lines only) and _rebaseline_2026_08_11_v3850_merge_storm_provider_registry (owner-authorized for this same file).",
"open-sse/executors/commandCode.ts": 1059,
"_rebaseline_2026_08_21_10859_vision_bridge_catalog": "#10859 own growth (Vision Bridge fixes #10808/#10809): src/lib/modelCapabilities.ts 1006->1016 (+10, cmd/gpt-5.3-codex* text-only capability resolution) and open-sse/executors/commandCode.ts 988->1023 (+35, Command Code wire-model normalization for bare ids + reasoning field fallback for opencode-routed gateways). Cohesive bug fixes at the existing capability-resolution / executor chokepoints; not extractable mid-fix. Covered by tests/unit/model-capabilities-command-code-codex-textonly-10703.test.ts, tests/unit/command-code-vision.test.ts, tests/unit/opencode-mimo-reasoning-details-nonstream.test.ts. Pushed directly to release (own-session miss: the original rebaseline was made in a throwaway validation worktree and never landed on the PR branch or the release before merge).",
"_rebaseline_2026_08_21_10907_sticky_pin_clear": "#10907 own growth: open-sse/executors/commandCode.ts 1023->1038 (+15, effort-suffix sanitization threading for the sticky-pin-clear fix). Cohesive change at the existing executor chokepoint. Covered by tests/unit/command-code-executor.test.ts.",
"_rebaseline_2026_08_21_10986_reasoning_only_content": "#10986 own growth: open-sse/executors/commandCode.ts 1038->1059 (+21, reasoning-only content fallback — when upstream emits only reasoning-delta events and never a text-delta, surface the reasoning text as message.content in createJsonResponse and emit a synthetic content delta in createStreamResponse). Cohesive bug fix at the existing executor chokepoint (mirrors precedent style of #10907/#10859). Covered by tests/unit/command-code-executor.test.ts (2 new cases: non-stream + streaming).",
"_rebaseline_2026_08_21_11069_m365_har_import": "#11069 own growth: AddApiKeyModal.tsx 1073->1080 (+7 = Import .har file button for the copilot-m365-web credential modal — M365 is the only provider whose credential (access_token+chathubPath) must be extracted from a DevTools HAR WebSocket URL, added as a new modal affordance). Cohesive UI at the existing modal chokepoint; not extractable. Covered by tests/unit/m365-har-import*.test.ts."
"_rebaseline_2026_08_21_11069_m365_har_import": "#11069 own growth: AddApiKeyModal.tsx 1073->1080 (+7 = Import .har file button for the copilot-m365-web credential modal — M365 is the only provider whose credential (access_token+chathubPath) must be extracted from a DevTools HAR WebSocket URL, added as a new modal affordance). Cohesive UI at the existing modal chokepoint; not extractable. Covered by tests/unit/m365-har-import*.test.ts.",
"_rebaseline_2026_08_23_tip_drift_post_batch0823": "Tip drift after the 2026-08-23 merge wave: chatBodyAdmission.ts 1009->1118 (+109, gate count incl. +1) and auth.ts 3337->3344 (+7), both grown by merges already on origin/release/v3.8.50 (verified identical on the pristine tip) — not by the codex-appserver-hardening PR that carries this bump. Owner pre-authorized baseline bumps 2026-08-22."
},
"_rebaseline_base_2026_08_10_proxyfetch": "Base-red fix (green-prs sweep, issue #9985): open-sse/utils/proxyFetch.ts 1207 > cap 1000 — new proxied-TLS fetch helper introduced by the Fal reference-image work. Owner-authorized quick rebaseline to green; structural slim tracked for v3.9.0.",
"_rebaseline_2026_07_27_v3849_train2": "Merge-train 2 (7 PRs) — owner-approved 2026-07-27. Single entry: chatCore.ts 4955->5006 (#8595, Responses multi-turn image compaction before the context hard-reject). Genuine irreducible growth at the existing compaction chokepoint in handleChatCore — the PR adds a last-resort retry against the concrete budget plus the estimateFinalInputTokens helper, both wired at the pre-existing call site rather than a new branch. Covered by tests/unit/8560-responses-image-compaction.test.ts (4 tests).",

View File

@@ -43,8 +43,21 @@ x-common: &common
- LIVE_WS_ALLOWED_ORIGINS=${LIVE_WS_ALLOWED_ORIGINS:-http://localhost:20128,http://127.0.0.1:20128}
- REDIS_URL=${REDIS_URL:-redis://redis:6379}
- NODE_OPTIONS=--max-old-space-size=2048
# Codex App-Server transport (provider: codex-app-server). Inert unless the
# `codex-app-server` compose profile is up (the sidecar below). Points the app
# at the internal sidecar; the capability token is shared via the mounted file.
- OMNIROUTE_CODEX_APPSERVER_WS=${OMNIROUTE_CODEX_APPSERVER_WS:-ws://codex-app-server:1456}
- OMNIROUTE_CODEX_APPSERVER_WS_TOKEN_FILE=${OMNIROUTE_CODEX_APPSERVER_WS_TOKEN_FILE:-/run/codex-appserver/token}
volumes:
- ./data:/app/data
# Shared capability token + codex auth for the app-server WS. Only meaningful
# when the codex-app-server profile is active. The token dir carries the WS
# capability token; the codex home is where the dashboard "Apply auth" writes
# ~/.codex/auth.json (getCliConfigPaths("codex") = <home>/.codex; the base
# image runs as `node`, so /home/node/.codex) and the SAME volume is mounted
# into the sidecar so its `codex app-server` reads the same auth.
- codex-appserver-token:/run/codex-appserver
- codex-appserver-home:/home/node/.codex
healthcheck:
test: ["CMD", "node", "healthcheck.mjs"]
interval: 30s
@@ -290,6 +303,59 @@ services:
profiles:
- cliproxyapi
# ── Profile: codex-app-server (Codex CLI app-server sidecar) ──────────
# A PLAIN Codex app-server for the `codex-app-server` provider: OmniRoute drives
# the Codex CLI's own `codex app-server` over JSON-RPC/WebSocket instead of
# replaying a session token to the API. It listens ONLY on the internal compose
# network (ws://codex-app-server:1456), guarded by a capability token — it is
# NEVER published to the host / internet. The Codex CLI (baked into
# omniroute:base) self-manages its OpenAI OAuth via the shared ~/.codex volume,
# which the dashboard "Apply auth" (device-OAuth) writes and this sidecar reads.
#
# NOTE: this is the GENERIC public sidecar. An operator wanting residential /
# UDP egress (via a TUN sidecar) runs that separately as an override; it is
# intentionally not shipped here.
codex-app-server:
image: omniroute:base
container_name: omniroute-codex-app-server
restart: unless-stopped
# Generate the WS capability token on first boot if absent, then run the
# app-server. entrypoint is overridden because the base image's default is the
# Next.js server.
entrypoint: ["/bin/sh", "-c"]
command:
- |
set -e
TOKEN_FILE=/run/codex-appserver/token
mkdir -p /run/codex-appserver
if [ ! -s "$$TOKEN_FILE" ]; then
# 32-byte hex capability token; shared with the app via the token volume.
TF="$$TOKEN_FILE" node -e 'require("fs").writeFileSync(process.env.TF, require("crypto").randomBytes(32).toString("hex"))' 2>/dev/null || \
{ head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n' > "$$TOKEN_FILE"; }
chmod 600 "$$TOKEN_FILE"
fi
exec codex app-server \
--listen ws://0.0.0.0:1456 \
--ws-auth capability-token \
--ws-token-file "$$TOKEN_FILE"
environment:
- CODEX_HOME=/home/node/.codex
- RUST_LOG=${CODEX_APPSERVER_RUST_LOG:-warn}
volumes:
- codex-appserver-token:/run/codex-appserver
- codex-appserver-home:/home/node/.codex
# No `ports:` — internal-only. Reached at ws://codex-app-server:1456 over the
# compose network by the omniroute app.
healthcheck:
test:
["CMD", "node", "-e", "require('http').get('http://127.0.0.1:1456/readyz',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
profiles:
- codex-app-server
volumes:
chatgpt-web-codex-browser-data:
name: omniroute-chatgpt-web-codex-browser-data
@@ -301,3 +367,7 @@ volumes:
name: omniroute-qdrant-data
bifrost-data:
name: omniroute-bifrost-data
codex-appserver-token:
name: omniroute-codex-appserver-token
codex-appserver-home:
name: omniroute-codex-appserver-home

View File

@@ -17,7 +17,7 @@ It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic acr
Core capabilities:
- OpenAI-compatible API surface for CLI/tools (338 providers, 100 executors)
- OpenAI-compatible API surface for CLI/tools (349 providers, 107 executors)
- Request/response translation across provider formats
- Model combo fallback (multi-model sequence)
- Structured combo steps (`provider + model + connection`) with runtime ordering by `compositeTiers`

View File

@@ -451,7 +451,7 @@ open-sse/
├── types.d.ts
├── config/ Provider registries, header profiles, identity, …
├── handlers/ Request handlers (chat, embeddings, audio, image, …)
├── executors/ 101 provider-specific HTTP executors
├── executors/ 107 provider-specific HTTP executors
├── translator/ Format conversion (OpenAI ↔ Claude ↔ Gemini ↔ Cursor ↔ Kiro)
├── transformer/ Responses API ↔ Chat Completions stream transformer
├── services/ 80+ service modules (combos, fallback, quotas, identity, …)

View File

@@ -6,7 +6,7 @@ lastUpdated: 2026-07-31
# OmniRoute Antigravity (Google One AI) Onboarding Guide
> **What you get**: Access to Gemini 3.1 Pro, Gemini 3.5 Flash, Claude Sonnet 4.6, and other models through your Google One AI Pro subscription — routed through OmniRoute as a unified gateway.
> **What you get**: Access to Gemini 3.1 Pro, Gemini 3.7 Flash, Claude Sonnet 4.6, and other models through your Google One AI Pro subscription — routed through OmniRoute as a unified gateway.
**Official references**:
@@ -45,7 +45,7 @@ Both providers share the **same Google backend** — identical OAuth client, tok
**Why the model catalog differs**: Google's CLI is "optimized for speed and low overhead" and "co-optimized with Gemini models" (per Google's official blog). The Web/IDE product is "optimized for comprehensiveness." The CLI uses `:fetchAvailableModels` to dynamically discover models, while the IDE uses a static curated list.
**In practice**: Use `agy/` prefix for Gemini models (e.g. `agy/gemini-3.5-flash-high`). Use `antigravity/` for the static curated list. Both hit the same Google backend, but expose different model naming. The quota is shared — using either provider counts against the same Google account's limits.
**In practice**: Use `agy/` prefix for Gemini models (e.g. `agy/gemini-3.7-flash-high`). Use `antigravity/` for the static curated list. Both hit the same Google backend, but expose different model naming. The quota is shared — using either provider counts against the same Google account's limits.
---

View File

@@ -0,0 +1,89 @@
---
title: "OpenAI Codex (App-Server) provider"
version: 3.8.50
lastUpdated: 2026-08-22
---
# OpenAI Codex — App-Server provider (`codex-app-server`)
OmniRoute exposes **two** ways to use OpenAI Codex:
| Provider | How it talks to OpenAI | Usage caveat |
|---|---|---|
| **`codex`** | Replays your ChatGPT/OpenAI OAuth token directly to the Responses API | **Yes** — the official session is not authorized for proxy/router use |
| **`codex-app-server`** | Drives the **Codex CLI's own `codex app-server`** over JSON-RPC/WebSocket; the CLI owns and self-refreshes its OAuth (`~/.codex/auth.json`) exactly like an interactive `codex` session | **No** — OmniRoute never replays a token to the API |
Because `codex-app-server` never replays a token, it does not carry the
session-replay usage caveat. It does require a **Codex CLI reachable at the
configured app-server URL**, and that CLI must be **signed in**.
---
## 1. Architecture
```
┌─ OmniRoute app ─────────────────┐ ┌─ codex-app-server sidecar ─────────┐
│ CodexAppServerExecutor │ WS │ codex app-server │
│ ws://codex-app-server:1456 ─────┼───────▶│ --listen ws://0.0.0.0:1456 │
│ (+ capability token) │ JSON │ --ws-auth capability-token │
│ │ RPC │ self-manages OpenAI OAuth │
└──────────────────────────────────┘ │ (~/.codex/auth.json, auto-refresh) │
│ shares (compose volumes) └─────────────────────────────────────┘
codex-appserver-token → the WS capability token (both mount it)
codex-appserver-home → ~/.codex (auth.json written by the dashboard,
read by the sidecar's codex app-server)
```
- The sidecar listens **only** on the internal compose network
(`ws://codex-app-server:1456`) behind a capability token. It is **never**
published to the host or internet.
- The Codex CLI is baked into `omniroute:base`, so no codex install is needed on
the host or the user's machine when you run the sidecar.
## 2. Bring it up
```bash
# Start the stack WITH the codex app-server sidecar profile:
docker compose --profile base --profile codex-app-server up -d
# (podman: podman compose --profile base --profile codex-app-server up -d)
```
The sidecar mints its WS capability token on first boot (into the shared
`codex-appserver-token` volume) and the app reads the same token via
`OMNIROUTE_CODEX_APPSERVER_WS_TOKEN_FILE`. No manual token wiring needed.
## 3. Connect + sign in
1. In the dashboard, add a connection for **OpenAI Codex (App-Server)**. No API
key or token is required (it's a no-auth provider — the sidecar owns auth).
2. If the sidecar's Codex CLI is **not yet signed in**, the connection health
check reports *"running but not signed in"* (not a red auth error). Use
**Sign in with ChatGPT**: this runs the standard Codex device-OAuth in your
browser and then writes `~/.codex/auth.json` into the shared volume via
**Apply auth** (the same one login serves both the `codex` and
`codex-app-server` providers).
3. Once signed in, the health check goes green (it verifies both `/readyz` **and**
`account/read` — i.e. up *and* authenticated) and turns work.
The dashboard never clobbers a healthy existing `~/.codex/auth.json` — it writes
only when the file is absent or its token is stale (a backup is always taken).
## 4. Deployment scenarios
- **Operator with an already-authenticated Codex CLI** — mount your host
`~/.codex` into the sidecar (`codex-appserver-home`) and skip the sign-in step.
- **Public user, no codex installed locally** — irrelevant: the sidecar has the
CLI. The user only authenticates through the dashboard.
- **Bare-metal OmniRoute (no sidecar, host codex)** — point
`OMNIROUTE_CODEX_APPSERVER_WS` at your own `codex app-server` and ensure the
host codex is signed in; the "codex not installed" hint appears if the binary
is missing.
## 5. Residential / UDP egress (operator extra, not shipped)
The generic sidecar above egresses over the container's normal network. An
operator who needs Codex traffic to egress via a **residential exit** (e.g. a TUN
tailscale sidecar carrying TCP + UDP/QUIC) runs that as a separate compose
override; it is intentionally **not** part of the shipped `codex-app-server`
profile. See the internal operations runbook for that setup.

View File

@@ -357,6 +357,49 @@ omniroute --port 3000
The CLI automatically loads `.env` from `~/.omniroute/.env` or `./.env`.
### Tray mode
Start OmniRoute in the system tray:
```bash
omniroute serve --tray
```
The command returns after the server and tray are ready.
The server continues without the terminal.
Tray mode supports macOS, Windows, and graphical Linux sessions. Tray mode does not open the dashboard automatically.
Use the tray menu for these actions:
- Open the dashboard.
- Open `/dashboard/logs`.
- Change auto-start.
- Stop OmniRoute.
Do not combine `--tray` with these options:
- `--daemon`
- `--log`
- `--no-recovery`
These modes require different process ownership.
Enable startup at the next machine login:
```bash
omniroute autostart enable
```
Auto-start uses tray mode on macOS, Windows, and graphical Linux sessions. Headless Linux uses the existing systemd user service.
Disable startup at login:
```bash
omniroute autostart disable
```
### Uninstalling
When you no longer need OmniRoute, we provide two quick scripts for a clean removal:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,390 +1,49 @@
# CLAUDE.md (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../CLAUDE.md) · 🇸🇦 [ar](../ar/CLAUDE.md) · 🇦🇿 [az](../az/CLAUDE.md) · 🇧🇬 [bg](../bg/CLAUDE.md) · 🇧🇩 [bn](../bn/CLAUDE.md) · 🇨🇿 [cs](../cs/CLAUDE.md) · 🇩🇰 [da](../da/CLAUDE.md) · 🇩🇪 [de](../de/CLAUDE.md) · 🇪🇸 [es](../es/CLAUDE.md) · 🇮🇷 [fa](../fa/CLAUDE.md) · 🇫🇮 [fi](../fi/CLAUDE.md) · 🇫🇷 [fr](../fr/CLAUDE.md) · 🇮🇳 [gu](../gu/CLAUDE.md) · 🇮🇱 [he](../he/CLAUDE.md) · 🇮🇳 [hi](../hi/CLAUDE.md) · 🇭🇺 [hu](../hu/CLAUDE.md) · 🇮🇩 [id](../id/CLAUDE.md) · 🇮🇩 [in](../in/CLAUDE.md) · 🇮🇹 [it](../it/CLAUDE.md) · 🇯🇵 [ja](../ja/CLAUDE.md) · 🇰🇷 [ko](../ko/CLAUDE.md) · 🇮🇳 [mr](../mr/CLAUDE.md) · 🇲🇾 [ms](../ms/CLAUDE.md) · 🇳🇱 [nl](../nl/CLAUDE.md) · 🇳🇴 [no](../no/CLAUDE.md) · 🇵🇭 [phi](../phi/CLAUDE.md) · 🇵🇱 [pl](../pl/CLAUDE.md) · 🇵🇹 [pt](../pt/CLAUDE.md) · 🇧🇷 [pt-BR](../pt-BR/CLAUDE.md) · 🇷🇴 [ro](../ro/CLAUDE.md) · 🇷🇺 [ru](../ru/CLAUDE.md) · 🇸🇰 [sk](../sk/CLAUDE.md) · 🇸🇪 [sv](../sv/CLAUDE.md) · 🇰🇪 [sw](../sw/CLAUDE.md) · 🇮🇳 [ta](../ta/CLAUDE.md) · 🇮🇳 [te](../te/CLAUDE.md) · 🇹🇭 [th](../th/CLAUDE.md) · 🇺🇦 [uk-UA](../uk-UA/CLAUDE.md) · 🇵🇰 [ur](../ur/CLAUDE.md) · 🇻🇳 [vi](../vi/CLAUDE.md) · 🇨🇳 [zh-CN](../zh-CN/CLAUDE.md)
🌐 **Languages:** 🇺🇸 [English](../../../CLAUDE.md) · 🇸🇦 [ar](../ar/CLAUDE.md) · 🇦🇿 [az](../az/CLAUDE.md) · 🇧🇬 [bg](../bg/CLAUDE.md) · 🇧🇩 [bn](../bn/CLAUDE.md) · 🇨🇿 [cs](../cs/CLAUDE.md) · 🇩🇰 [da](../da/CLAUDE.md) · 🇩🇪 [de](../de/CLAUDE.md) · 🇪🇸 [es](../es/CLAUDE.md) · 🇮🇷 [fa](../fa/CLAUDE.md) · 🇫🇮 [fi](../fi/CLAUDE.md) · 🇫🇷 [fr](../fr/CLAUDE.md) · 🇮🇳 [gu](../gu/CLAUDE.md) · 🇮🇱 [he](../he/CLAUDE.md) · 🇮🇳 [hi](../hi/CLAUDE.md) · 🇭🇺 [hu](../hu/CLAUDE.md) · 🇮🇩 [id](../id/CLAUDE.md) · 🇮🇩 [in](../in/CLAUDE.md) · 🇮🇹 [it](../it/CLAUDE.md) · 🇯🇵 [ja](../ja/CLAUDE.md) · 🇰🇷 [ko](../ko/CLAUDE.md) · 🇮🇳 [mr](../mr/CLAUDE.md) · 🇲🇾 [ms](../ms/CLAUDE.md) · 🇳🇱 [nl](../nl/CLAUDE.md) · 🇳🇴 [no](../no/CLAUDE.md) · 🇵🇭 [phi](../phi/CLAUDE.md) · 🇵🇱 [pl](../pl/CLAUDE.md) · 🇵🇹 [pt](../pt/CLAUDE.md) · 🇧🇷 [pt-BR](../pt-BR/CLAUDE.md) · 🇷🇴 [ro](../ro/CLAUDE.md) · 🇷🇺 [ru](../ru/CLAUDE.md) · 🇸🇰 [sk](../sk/CLAUDE.md) · 🇸🇪 [sv](../sv/CLAUDE.md) · 🇰🇪 [sw](../sw/CLAUDE.md) · 🇮🇳 [ta](../ta/CLAUDE.md) · 🇮🇳 [te](../te/CLAUDE.md) · 🇹🇭 [th](../th/CLAUDE.md) · 🇹🇷 [tr](../tr/CLAUDE.md) · 🇺🇦 [uk-UA](../uk-UA/CLAUDE.md) · 🇵🇰 [ur](../ur/CLAUDE.md) · 🇻🇳 [vi](../vi/CLAUDE.md) · 🇨🇳 [zh-CN](../zh-CN/CLAUDE.md)
---
Bu dosya, bu depoda kod çalıştırırken Claude Code (claude.ai/code) için rehberlik sağlar.
@AGENTS.md
## Hızlı Başlangıç
**Tüm proje kuralları [`AGENTS.md`](AGENTS.md) dosyasında yer almaktadır** — her yapay zeka asistanı için tek doğruluk kaynağıdır (mimari, kurallar, testler, kalite kapıları, git iş akışı, 23 Katı Kural, PII öğrenimleri). Tamamını okuyun; buraya yeniden proje kuralları eklemeyin. Aşağıdaki her şey YALNIZCA Claude Code için geçerlidir — `AGENTS.md` içinde zaten tanımlanmış kuralların operasyonel ayrıntılarıdır.
```bash
npm install # Bağımlılıkları yükle (otomatik olarak .env.example'dan .env oluşturur)
npm run dev # Geliştirme sunucusu http://localhost:20128
npm run build # Üretim derlemesi (Next.js 16 bağımsız)
npm run lint # ESLint (0 hata bekleniyor; uyarılar önceden mevcut)
npm run typecheck:core # TypeScript kontrolü (temiz olmalı)
npm run typecheck:noimplicit:core # Sıkı kontrol (implicit any yok)
npm run test:coverage # Birim testleri + kapsama kapısı (75/75/75/70 — ifadeler/hatlar/fonksiyonlar/dallar)
npm run check # lint + test birleştirilmiş
npm run check:cycles # Dairesel bağımlılıkları tespit et
```
## Worktree İzolasyonu — Claude Code Özel Notları
### Testleri Çalıştırma
Tam zorunlu worktree protokolü (hedef dal onayı, `.claude/worktrees/` kurallı yolu, `cp -al` node_modules, kaldırma kuralları) `AGENTS.md` → Git Workflow → "Worktree isolation" bölümündedir. Claude Code özel noktaları:
```bash
# Tek test dosyası (Node.js yerel test koşucusu — çoğu test)
node --import tsx/esm --test tests/unit/your-file.test.ts
- Operatör daha önce belirtmediyse, hedef dalı `AskUserQuestion` (Katı Kural #19) ile onaylayın.
- Yerel `EnterWorktree` aracını tercih edin — worktree'leri zaten `.claude/worktrees/` altında oluşturur (kurallı yol). Belgelenen `git worktree add` komutuyla worktree oluşturun, ardından `path` parametresi ile `EnterWorktree` çağırın.
# Vitest (MCP sunucusu, autoCombo, önbellek)
npm run test:vitest
## Oturumlar Arası Güvenlik — Claude Code Özel Notları
# Tüm test paketleri
npm run test:all
```
Katı Kurallar #19/#21/#22 (`AGENTS.md` içinde) paralel oturumları yönetir. Bu ortam için operasyonel hatırlatmalar:
Tam test matrisini görmek için `CONTRIBUTING.md` → "Testleri Çalıştırma" kısmına bakın. Derin mimari için `AGENTS.md` dosyasına bakın.
- **Git'e dokunan her alt ajanın isteminde `git stash` yasağını kelimesi kelimesine tekrarlayın** (Agent tool / Workflow betikleri) — alt ajanlar bu dosyayı devralmaz ve kaydedilen stash olayı bir alt ajan aracılığıyla gerçekleşti.
- _Bu oturumda_ oluşturmadığınız herhangi bir PR'ı birleştirmeden veya push etmeden önce `git worktree list` çalıştırın ve `gh pr view <N> --json state,headRefOid` kontrolü yapın (Katı Kural #22b).
- Her oturumu, ana checkout başladığı dalda olacak şekilde sonlandırın.
---
## Superpowers / Planlama Yapıtları — Yol Geçersiz Kılmaları
## Projeye Genel Bakış
`_tasks/` kuralı `AGENTS.md` → "Planning & Research Artifacts" içinde tanımlanmıştır. Superpowers yetenekleri `docs/…` dizinini işaret eden varsayılanlarla gelir — bu varsayılanlar **burada geçersiz kılınmıştır**. Bir superpowers yeteneği "saved to `docs/superpowers/plans/…`" gibi bir yol duyurduğunda, yazmadan önce onu `_tasks/…` eşdeğerine yeniden yazın:
**OmniRoute** — birleşik AI proxy/yönlendirici. Tek uç nokta, 329 LLM sağlayıcısı, otomatik geri dönüş.
| Yapıt (Yetenek) | Varsayılan (KULLANMAYIN) | Bunun yerine buraya kaydedin |
| ---------------------------------- | ------------------------- | ------------------------------------------------------------- |
| Planlar (`writing-plans`) | `docs/superpowers/plans/` | `_tasks/superpowers/plans/YYYY-MM-DD-<feature>.md` |
| Şartnameler / tasarım (`brainstorming`) | `docs/superpowers/specs/` | `_tasks/superpowers/specs/YYYY-MM-DD-<topic>-design.md` |
| Araştırma (`deep-research`, ad-hoc)| `docs/research/` | `_tasks/research/…` |
| Devirler (`/handoff`) | — | `_tasks/hands-off/<YYYY-MM-DD>_<branch>_v<versão>_sess-<id>/` |
| Katman | Konum | Amaç |
| ------------- | ----------------------- | ------------------------------------------------------------------------- |
| API Yolları | `src/app/api/v1/` | Next.js Uygulama Yönlendiricisi — giriş noktaları |
| İşleyiciler | `open-sse/handlers/` | İstek işleme (sohbet, gömme, vb.) |
| Yürütücüler | `open-sse/executors/` | Sağlayıcıya özel HTTP dağıtımı |
| Çeviriciler | `open-sse/translator/` | Format dönüşümü (OpenAI↔Claude↔Gemini) |
| Dönüştürücü | `open-sse/transformer/` | Yanıtlar API ↔ Sohbet Tamamlamaları |
| Hizmetler | `open-sse/services/` | Kombinasyon yönlendirme, hız sınırlamaları, önbellekleme, vb. |
| Veritabanı | `src/lib/db/` | 110 top-level SQLite domain modules, 130 migrations |
| Alan/Politika | `src/domain/` | Politika motoru, maliyet kuralları, geri dönüş mantığı |
| MCP Sunucusu | `open-sse/mcp-server/` | 107 unique tools, 3 transports (stdio / SSE / Streamable HTTP), 32 scopes |
| A2A Sunucusu | `src/lib/a2a/` | JSON-RPC 2.0 ajan protokolü |
| Beceriler | `src/lib/skills/` | Genişletilebilir beceri çerçevesi |
| Bellek | `src/lib/memory/` | Kalıcı konuşma belleği |
Bu yapıtları `_tasks/` deposu içinde commit edin (`git -C _tasks …`), asla ana depoda değil.
Monorepo: `src/` (Next.js 16 uygulaması), `open-sse/` (akış motoru çalışma alanı), `electron/` (masaüstü uygulaması), `tests/`, `bin/` (CLI giriş noktası).
## Geçici Dosyalar — `/tmp` Değil `_artifacts/` Kullanın
---
Bu proje, çalışma ortamının varsayılan oturum karalama alanını (`/tmp/claude-*/…`) geçersiz kılar. Geçici/çalışma dosyalarını — dışa aktarmaları, oluşturulan zip'leri, tek seferlik ara çıktıları, aksi halde `/tmp` içine koyacağınız her şeyi — bunun yerine `/home/diegosouzapw/dev/proxys/OmniRoute/_artifacts/` dizinine yazın.
## İstek Boru Hattı
- `_artifacts/` bir kök `_*` yoludur: zaten gitignore edilmiştir (`AGENTS.md` → "Root `_*` paths"), yalnızca diskte yaşar, asla takip edilmez.
- Gerekçe: karalama çıktılarını proje içinde tutmak (vs `/tmp`), operatörün geçici her şeyi tek bir yerde bulup silmesini kolaylaştırır.
- Bunu `_tasks/` (Katı Kural #23, kalıcı planlar/şartnameler/araştırmalar için kendi özel git deposu) ile **karıştırmayın**`_artifacts/` yalnızca tek kullanımlık çalışma dosyaları içindir.
```
Client → /v1/chat/completions (Next.js route)
→ CORS → Zod doğrulama → kimlik doğrulama? → politika kontrolü → istemci enjeksiyon koruması
→ handleChatCore() [open-sse/handlers/chatCore.ts]
→ önbellek kontrolü → oran sınırlaması → kombinasyon yönlendirmesi?
→ resolveComboTargets() → hedef başına handleSingleModel()
→ translateRequest() → getExecutor() → executor.execute()
→ fetch() yukarı akış → geri çekilme ile yeniden deneme
→ yanıt çevirisi → SSE akışı veya JSON
→ Eğer Yanıtlar API'si: responsesTransformer.ts TransformStream
```
## PR Açmadan Önce Base-Green Kontrolü
API yolları tutarlı bir desen izler: `Route → CORS ön uç → Zod gövde doğrulama → Opsiyonel kimlik doğrulama (extractApiKey/isValidApiKey) → API anahtarı politika uygulaması → İşleyici delegasyonu (open-sse)`. Global Next.js ara yazılımı yok — kesme işlemi yol spesifik.
**Combo routing** (`open-sse/services/combo.ts`): 19 public strategies (priority, weighted, fill-first, round-robin, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, cache-optimized, context-relay, fusion, pipeline). Each target calls `handleSingleModel()`, which wraps `handleChatCore()` with per-target error handling and circuit-breaker checks. See `docs/routing/AUTO-COMBO.md` for the 13-factor Auto-Combo scoring and `docs/architecture/RESILIENCE_GUIDE.md` for the 3 resilience layers.
---
## Dayanıklılık Çalışma Durumu
OmniRoute, üç ilgili ancak farklı geçici hata mekanizmasına sahiptir. Yönlendirme davranışını hata ayıklarken kapsamlarını ayrı tutun. Bir bakışta harita için [3 katmanlı dayanıklılık diyagramı](./docs/diagrams/exported/resilience-3layers.svg) (kaynak: [docs/diagrams/resilience-3layers.mmd](./docs/diagrams/resilience-3layers.mmd))'na bakın.
### Sağlayıcı Devre Kesici
**Kapsam**: tüm sağlayıcı, örneğin `glm`, `openai`, `anthropic`.
**Amaç**: yukarı akış/hizmet seviyesinde sürekli olarak başarısız olan bir sağlayıcıya trafik göndermeyi durdurmak, böylece bir sağlıksız sağlayıcı her isteği yavaşlatmaz.
**Uygulama**:
- Temel sınıf: `src/shared/utils/circuitBreaker.ts`
- Sohbet kapısı/uygulama kablolaması: `src/sse/handlers/chatHelpers.ts`, `src/sse/handlers/chat.ts`
- Çalışma durumu API'si: `src/app/api/monitoring/health/route.ts`
- Paylaşılan sarmalayıcılar: `open-sse/services/accountFallback.ts`
- Kalıcı durum tablosu: `domain_circuit_breakers`
**Durumlar**:
- `CLOSED`: normal trafik izin verilir.
- `OPEN`: sağlayıcı geçici olarak engellenmiştir; arayanlar bir sağlayıcı-devre-açık yanıtı alır veya kombinasyon yönlendirmesi başka bir hedefe atlar.
- `HALF_OPEN`: sıfırlama zaman aşımı dolmuştur; bir prob isteğine izin verilir. Başarı devre kesiciyi kapatır, başarısızlık tekrar açar.
**Varsayılanlar** (`open-sse/config/constants.ts`):
- OAuth sağlayıcıları: eşik `3`, sıfırlama zaman aşımı `60s`.
- API anahtarı sağlayıcıları: eşik `5`, sıfırlama zaman aşımı `30s`.
- Yerel sağlayıcılar: eşik `2`, sıfırlama zaman aşımı `15s`.
Sadece sağlayıcı düzeyindeki hata durumları sağlayıcı devre kesicisini tetiklemelidir:
```ts
(408, 500, 502, 503, 504);
```
Normal hesap/anahtar/model hataları gibi çoğu `401`, `403` veya `429` durumları için tüm sağlayıcı devre kesicisini tetiklemeyin. Bunlar genellikle bağlantı soğuma veya model kilitlenmesi ile ilgilidir. Genel bir API anahtarı sağlayıcı `403` kurtarılabilir olmalıdır, aksi takdirde terminal sağlayıcı/hesap hatası olarak sınıflandırılır.
Devre kesici tembel kurtarma kullanır, arka planda bir zamanlayıcı değil. `OPEN` süresi dolduğunda, `getStatus()`, `canExecute()` ve `getRetryAfterMs()` gibi okumalar durumu `HALF_OPEN` olarak yeniler, böylece paneller ve kombinasyon aday oluşturucuları süresi dolmuş bir sağlayıcıyı sonsuza kadar hariç tutmaz.
### Bağlantı Soğuma
**Kapsam**: bir sağlayıcı bağlantısı/hesap/anahtar.
**Amaç**: aynı sağlayıcı için diğer bağlantıların istekleri karşılamaya devam etmesine izin verirken, bir kötü anahtar/hesabı geçici olarak atlamak.
**Uygulama**:
- Yazma/güncelleme yolu: `src/sse/services/auth.ts::markAccountUnavailable()`
- Hesap seçimi/filtreleme: `src/sse/services/auth.ts::getProviderCredentials...`
- Soğuma hesaplaması: `open-sse/services/accountFallback.ts::checkFallbackError()`
- Ayarlar: `src/lib/resilience/settings.ts`
Sağlayıcı bağlantılarındaki önemli alanlar:
```ts
rateLimitedUntil;
testStatus: "unavailable";
lastError;
lastErrorType;
errorCode;
backoffLevel;
```
Hesap seçimi sırasında, bir bağlantı atlanırken:
```ts
new Date(rateLimitedUntil).getTime() > Date.now();
```
Soğumalar da tembel: `rateLimitedUntil` geçmişte olduğunda, bağlantı tekrar uygun hale gelir. Başarılı kullanımda, `clearAccountError()` `testStatus`, `rateLimitedUntil`, hata alanlarını ve `backoffLevel`'ı temizler.
Varsayılan bağlantı soğuma davranışı:
- OAuth temel soğuma: `5s`.
- API anahtarı temel soğuma: `3s`.
- API anahtarı `429`, mevcut olduğunda yukarı akış yeniden deneme ipuçlarını (`Retry-After`, sıfırlama başlıkları veya ayrıştırılabilir sıfırlama metni) tercih etmelidir.
- Tekrarlanan kurtarılabilir hatalar üstel geri çekilme kullanır:
```ts
baseCooldownMs * 2 ** failureIndex;
```
Anti-thundering-herd koruması, aynı bağlantıda eşzamanlı hataların soğumayı sürekli uzatmasını veya `backoffLevel`'ı iki katına çıkarmasını önler.
Terminal durumlar soğumalar değildir. `banned`, `expired` ve `credits_exhausted` kimlik bilgileri/ayarlar değişene kadar veya bir operatör bunları sıfırlayana kadar kullanılamaz durumda kalması amaçlanmıştır. Terminal durumları geçici soğuma durumu ile üzerine yazmayın.
### Model Kilitlenmesi
**Kapsam**: sağlayıcı + bağlantı + model.
**Amaç**: yalnızca bir modelin kullanılamaz veya kota sınırlı olduğu durumlarda tüm bağlantıyı devre dışı bırakmaktan kaçınmak.
Örnekler:
- Her model için kota sağlayıcıları `429` döndürüyor.
- Bir eksik model için `404` döndüren yerel sağlayıcılar.
- Seçilen Grok modları gibi sağlayıcıya özgü mod/model izin hataları.
Model kilitlenmesi `open-sse/services/accountFallback.ts` içinde yer alır ve aynı bağlantının diğer modelleri sunmaya devam etmesine izin verir.
### Hata Ayıklama Rehberi
- Bir sağlayıcı için tüm anahtarlar atlanıyorsa, hem sağlayıcı devre kesici durumunu hem de her bağlantının `rateLimitedUntil`/`testStatus`'ını kontrol edin.
- Bir sağlayıcı sıfırlama penceresinden sonra kalıcı olarak hariç tutuluyorsa, kodun `getStatus()`/`canExecute()` yerine ham `state` okuduğundan emin olun.
- Bir sağlayıcı anahtarı başarısız olursa ancak diğerleri çalışıyorsa, sağlayıcı devre kesicisi yerine bağlantı soğumasını tercih edin.
- Sadece bir model başarısız olursa, bağlantı soğuması yerine model kilitlenmesini tercih edin.
- Bir durum kendiliğinden kurtulmalıysa, gelecekteki bir zaman damgasına/sıfırlama zaman aşımına ve süresi dolmuş durumu yenileyen bir okuma yoluna sahip olmalıdır. Kalıcı durumlar manuel kimlik bilgisi veya yapılandırma değişiklikleri gerektirir.
## Anahtar Sözleşmeler
### Kod Stili
- **2 boşluk**, noktalı virgüller, çift tırnak, 100 karakter genişliği, es5 son virgüller (lint-staged tarafından Prettier ile zorunlu kılınır)
- **İthalatlar**: harici → dahili (`@/`, `@omniroute/open-sse`) → göreceli
- **İsimlendirme**: dosyalar=camelCase/kebab, bileşenler=PascalCase, sabitler=UPPER_SNAKE
- **ESLint**: `no-eval`, `no-implied-eval`, `no-new-func` = her yerde hata; `no-explicit-any` = `open-sse/` ve `tests/` içinde uyarı
- **TypeScript**: `strict: false`, hedef ES2022, modül esnext, çözümleyici paketleyici. Açık türleri tercih edin.
### Veritabanı
- **Her zaman** `src/lib/db/` alan modüllerinden geçin — **asla** rotalarda veya işleyicilerde ham SQL yazmayın
- **Asla** `src/lib/localDb.ts` içine mantık eklemeyin (sadece yeniden ihracat katmanı)
- **Asla** `localDb.ts`'den silindirik ithalat yapmayın — bunun yerine belirli `db/` modüllerini içe aktarın
- DB singleton: `getDbInstance()` `src/lib/db/core.ts`'den (WAL günlüğü)
- Göçler: `src/lib/db/migrations/` — sürümlü SQL dosyaları, idempotent, işlemler içinde çalıştırılır
### Hata Yönetimi
- belirli hata türleri ile try/catch, pino bağlamı ile günlüğe kaydet
- SSE akışlarında hataları yutmayın — temizlik için iptal sinyalleri kullanın
- Uygun HTTP durum kodlarını döndürün (4xx/5xx)
### Güvenlik
- **Asla** `eval()`, `new Function()`, veya dolaylı eval kullanmayın
- Tüm girdileri Zod şemaları ile doğrulayın
- Kimlik bilgilerini dinlenirken şifreleyin (AES-256-GCM)
- Yukarı akış başlıkları yasak listesi: `src/shared/constants/upstreamHeaders.ts` — düzenlerken temizleme, Zod şemaları ve birim testlerinin uyumlu kalmasını sağlayın
- **Halka açık yukarı akış kimlik bilgileri** (Gemini/Antigravity/Windsurf tarzı OAuth client_id/secret + halka açık CLI'lerden çıkarılan Firebase Web anahtarları): **MUTLAKA** `resolvePublicCred()` ile gömülmelidir `open-sse/utils/publicCreds.ts`'den — **asla** dize sabitleri olarak. Zorunlu desen için `docs/security/PUBLIC_CREDS.md`'ye bakın.
- **Hata yanıtları** (HTTP / SSE / yürütücü / MCP işleyici): **MUTLAKA** `buildErrorBody()` veya `sanitizeErrorMessage()` üzerinden yönlendirilmelidir `open-sse/utils/error.ts`'den — **asla** ham `err.stack` veya `err.message`'i bir yanıt gövdesine koymayın. `docs/security/ERROR_SANITIZATION.md`'ye bakın.
- **Değişkenlerden oluşturulan kabuk komutları**: `exec()`/`spawn()` ile çalışma zamanı değerlerine ihtiyaç duyan bir betik çağırırken, bunları `env` seçeneği aracılığıyla geçirin (otomatik olarak kabukta kaçış yapılır) — **asla** güvenilmeyen/dış yolları betik gövdesine dize ile birleştirmeyin. Referans: `src/mitm/cert/install.ts::updateNssDatabases`.
- **Varsayılan olarak güvenli kütüphaneler** ([tldrsec/awesome-secure-defaults](https://github.com/tldrsec/awesome-secure-defaults)): yeni güvenlik hassas yüzeyleri eklerken, özel uygulamalar yerine Helmet.js, DOMPurify, ssrf-req-filter, safe-regex, Google Tink'i tercih edin.
---
## Yaygın Değişiklik Senaryoları
### Yeni Bir Sağlayıcı Ekleme
1. `src/shared/constants/providers.ts` içinde kaydedin (yükleme sırasında Zod ile doğrulanır)
2. Özel mantık gerekiyorsa `open-sse/executors/` içinde yürütücü ekleyin ( `BaseExecutor`'ı genişletin)
3. OpenAI dışı bir format varsa `open-sse/translator/` içinde çevirmen ekleyin
4. OAuth tabanlı ise `src/lib/oauth/constants/oauth.ts` içinde OAuth yapılandırması ekleyin — yukarı akış CLI'si halka açık bir client_id/secret gönderiyorsa, `resolvePublicCred()` aracılığıyla gömün (bkz. `docs/security/PUBLIC_CREDS.md`), **asla** bir literal olarak
5. `open-sse/config/providerRegistry.ts` içinde modelleri kaydedin
6. `tests/unit/` içinde testler yazın (yeni bir gömülü varsayılan eklediyseniz publicCreds şekil doğrulamasını dahil edin)
### Yeni Bir API Rotası Ekleme
1. `src/app/api/v1/your-route/` altında dizin oluşturun
2. `GET`/`POST` işleyicileri ile `route.ts` oluşturun
3. Deseni takip edin: CORS → Zod gövde doğrulaması → isteğe bağlı kimlik doğrulama → işleyici delegasyonu
4. İşleyici `open-sse/handlers/` içinde yer alır (oradan içe aktarın, satır içinde değil)
5. Hata yanıtları `buildErrorBody()` / `errorResponse()` kullanır `open-sse/utils/error.ts`'den (otomatik olarak temizlenir — asla `err.stack` veya `err.message`'i ham olarak gövdeye koymayın). `docs/security/ERROR_SANITIZATION.md`'ye bakın.
6. Testler ekleyin — hata yanıtlarının yığın izlerini sızdırmadığını doğrulayan en az bir doğrulama dahil edin (`!body.error.message.includes("at /")`)
### Yeni Bir DB Modülü Ekleme
1. `src/lib/db/yourModule.ts` oluşturun — `./core.ts`'den `getDbInstance`'i içe aktarın
2. Alan tablonuz için CRUD işlevlerini dışa aktarın
3. Yeni tablolara ihtiyaç varsa `src/lib/db/migrations/` içinde göç ekleyin
4. `src/lib/localDb.ts`'den yeniden dışa aktarın (sadece yeniden dışa aktarma listesine ekleyin)
5. Testler yazın
### Yeni Bir MCP Aracı Ekleme
1. Zod girdi şeması + asenkron işleyici ile `open-sse/mcp-server/tools/` içinde araç tanımını ekleyin
2. Araç setinde kaydedin ( `createMcpServer()` ile bağlanır)
3. Uygun kapsam(lar)a atayın
4. Testler yazın (araç çağrısı `mcp_audit` tablosuna kaydedilir)
### Yeni Bir A2A Yeteneği Ekleme
1. `src/lib/a2a/skills/` içinde yetenek oluşturun (zaten 5 tane var: akıllı yönlendirme, kota yönetimi, sağlayıcı keşfi, maliyet analizi, sağlık raporu)
2. Yetenek görev bağlamını alır (mesajlar, meta veriler) → yapılandırılmış sonuç döndürür
3. `src/lib/a2a/taskExecution.ts` içinde `A2A_SKILL_HANDLERS`'da kaydedin
4. `src/app/.well-known/agent.json/route.ts` içinde açığa çıkarın (Agent Kartı)
5. `tests/unit/` içinde testler yazın
6. `docs/frameworks/A2A-SERVER.md` içinde yetenek tablosunu belgeleyin
### Yeni Bir Bulut Ajanı Ekleme
1. `src/lib/cloudAgent/agents/` içinde `CloudAgentBase`'i genişleten ajan sınıfı oluşturun (zaten 3 tane var: codex-cloud, devin, jules)
2. `createTask`, `getStatus`, `approvePlan`, `sendMessage`, `listSources`'ı uygulayın
3. `src/lib/cloudAgent/registry.ts` içinde kaydedin
4. Gerekirse OAuth/kimlik bilgileri yönetimini ekleyin (`src/lib/oauth/providers/`)
5. Testler + `docs/frameworks/CLOUD_AGENT.md` içinde belgeleyin
### Yeni Bir Guardrail / Eval / Yetenek / Webhook olayı Ekleme
- Guardrail: `src/lib/guardrails/` → belgeler: `docs/security/GUARDRAILS.md`
- Eval paketi: `src/lib/evals/` → belgeler: `docs/frameworks/EVALS.md`
- Yetenek (sandbox): `src/lib/skills/` → belgeler: `docs/frameworks/SKILLS.md`
- Webhook olayı: `src/lib/webhookDispatcher.ts` → belgeler: `docs/frameworks/WEBHOOKS.md`
## Referans Dokümantasyonu
Herhangi bir önemsiz değişiklik için, önce ilgili derinlemesine incelemeyi okuyun:
| Alan | Doküman |
| -------------------------------------------------------- | ----------------------------------------------------------------- |
| Repo navigasyonu | `docs/architecture/REPOSITORY_MAP.md` |
| Mimari | `docs/architecture/ARCHITECTURE.md` |
| Mühendislik referansı | `docs/architecture/CODEBASE_DOCUMENTATION.md` |
| Auto-Combo (13-factor scoring, 19 public strategies) | `docs/routing/AUTO-COMBO.md` |
| Dayanıklılık (3 mekanizma) | `docs/architecture/RESILIENCE_GUIDE.md` |
| Akıl yürütme tekrarları | `docs/routing/REASONING_REPLAY.md` |
| Yetenekler çerçevesi | `docs/frameworks/SKILLS.md` |
| Bellek sistemi (FTS5 + Qdrant) | `docs/frameworks/MEMORY.md` |
| Bulut ajanları | `docs/frameworks/CLOUD_AGENT.md` |
| Koruma önlemleri (Kişisel Veriler / enjeksiyon / vizyon) | `docs/security/GUARDRAILS.md` |
| Kamu üst akış kimlik bilgileri (Gemini/vb.) | `docs/security/PUBLIC_CREDS.md` |
| Hata mesajı temizleme | `docs/security/ERROR_SANITIZATION.md` |
| Değerlendirmeler | `docs/frameworks/EVALS.md` |
| Uyum / denetim | `docs/security/COMPLIANCE.md` |
| Webhook'lar | `docs/frameworks/WEBHOOKS.md` |
| Yetkilendirme akışı | `docs/architecture/AUTHZ_GUIDE.md` |
| Gizlilik (TLS / parmak izi) | `docs/security/STEALTH_GUIDE.md` |
| Ajan protokolleri (A2A / ACP / Bulut) | `docs/frameworks/AGENT_PROTOCOLS_GUIDE.md` |
| MCP sunucusu | `docs/frameworks/MCP-SERVER.md` |
| A2A sunucusu | `docs/frameworks/A2A-SERVER.md` |
| API referansı + OpenAPI | `docs/reference/API_REFERENCE.md` + `docs/reference/openapi.yaml` |
| Sağlayıcı kataloğu (otomatik oluşturulmuş) | `docs/reference/PROVIDER_REFERENCE.md` |
| Sürüm akışı | `docs/ops/RELEASE_CHECKLIST.md` |
## Test Etme
| Ne | Komut |
| ----------------------- | ----------------------------------------------------------------------------- |
| Birim testleri | `npm run test:unit` |
| Tek dosya | `node --import tsx/esm --test tests/unit/file.test.ts` |
| Vitest (MCP, autoCombo) | `npm run test:vitest` |
| E2E (Playwright) | `npm run test:e2e` |
| Protokol E2E (MCP+A2A) | `npm run test:protocols:e2e` |
| Ekosistem | `npm run test:ecosystem` |
| Kapsam kapısı | `npm run test:coverage` (75/75/75/70 — ifadeler/hatlar/fonksiyonlar/kolonlar) |
| Kapsam raporu | `npm run coverage:report` |
**PR kuralı**: Eğer `src/`, `open-sse/`, `electron/` veya `bin/` içindeki üretim kodunu değiştirirseniz, aynı PR içinde testleri eklemeli veya güncellemelisiniz.
**Test katmanı tercihi**: birim önce → entegrasyon (çok modüllü veya DB durumu) → e2e (sadece UI/iş akışı). Hata yeniden üretimlerini düzeltmeden önce veya yanında otomatik testler olarak kodlayın.
**Copilot kapsam politikası**: Bir PR üretim kodunu değiştiriyorsa ve kapsam %75'in (ifadeler/hatlar/fonksiyonlar) veya %70'in (kolonlar) altındaysa, sadece rapor etmekle kalmayın — test ekleyin veya güncelleyin, kapsam kapısını yeniden çalıştırın, ardından onay isteyin. Çalıştırılan komutları, değiştirilen test dosyalarını ve son kapsam sonucunu PR raporuna dahil edin.
---
## Git İş Akışı
```bash
# Asla doğrudan main'e commit yapmayın
git checkout -b feat/your-feature
git commit -m "feat: değişikliğinizi tanımlayın"
git push -u origin feat/your-feature
```
**Dal ön ekleri**: `feat/`, `fix/`, `refactor/`, `docs/`, `test/`, `chore/`
**Commit formatı** (Geleneksel Commits): `feat(db): devre kesici ekle` — kapsamlar: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`
**Husky kancaları**:
- **pre-commit**: lint-staged + `check-docs-sync` + `check:any-budget:t11`
- **pre-push**: `npm run test:unit`
---
## Ortam
- **Çalışma Zamanı**: Node.js ≥20.20.2 <21 |
| ≥22.22.2 <23 |
| ≥24 <25, ES Modülleri
- **TypeScript**: 5.9+, hedef ES2022, modül esnext, çözümleyici paketleyici
- **Yol takma adları**: `@/*``src/`, `@omniroute/open-sse``open-sse/`, `@omniroute/open-sse/*``open-sse/*`
- **Varsayılan port**: 20128 (API + kontrol paneli aynı portta)
- **Veri dizini**: `DATA_DIR` env değişkeni, varsayılan olarak `~/.omniroute/`
- **Ana env değişkenleri**: `PORT`, `JWT_SECRET`, `API_KEY_SECRET`, `INITIAL_PASSWORD`, `REQUIRE_API_KEY`, `APP_LOG_LEVEL`
- Kurulum: `cp .env.example .env` ardından `JWT_SECRET` (`openssl rand -base64 48`) ve `API_KEY_SECRET` (`openssl rand -hex 32`) oluşturun
---
## Sert Kurallar
1. Asla gizli bilgileri veya kimlik bilgilerini commit etmeyin
2. Asla `localDb.ts` içine mantık eklemeyin
3. Asla `eval()` / `new Function()` / dolaylı eval kullanmayın
4. Asla doğrudan `main`'e commit yapmayın
5. Asla rotalarda ham SQL yazmayın — `src/lib/db/` modüllerini kullanın
6. Asla SSE akışlarında hataları sessizce yutmayın
7. Her zaman Zod şemaları ile girdileri doğrulayın
8. Üretim kodunu değiştirirken her zaman testleri dahil edin
9. Kapsam ≥%75 (ifadeler, hatlar, fonksiyonlar) / ≥%70 (kolonlar) olmalıdır. Mevcut ölçülen: ~%82.
10.ık operatör onayı olmadan Husky kancalarını (`--no-verify`, `--no-gpg-sign`) asla atlamayın.
11. Asla kamuya açık yukarı akış OAuth client_id/secret veya Firebase Web anahtarlarını string literal olarak gömün — her zaman `resolvePublicCred()` üzerinden geçin (`open-sse/utils/publicCreds.ts`). `docs/security/PUBLIC_CREDS.md`'ye bakın.
12. Asla HTTP / SSE / yürütücü yanıtlarında ham `err.stack` / `err.message` döndürmeyin — her zaman `buildErrorBody()` veya `sanitizeErrorMessage()` üzerinden yönlendirin (`open-sse/utils/error.ts`). `docs/security/ERROR_SANITIZATION.md`'ye bakın.
13. Asla dış yolları veya çalışma zamanı değerlerini `exec()`/`spawn()`'a geçirilen shell betiklerine string-interpolate etmeyin — bunun yerine `env` seçeneği aracılığıyla geçirin. Referans: `src/mitm/cert/install.ts::updateNssDatabases`.
14. Asla bir CodeQL / Secret-Scanning uyarısını (a) yukarıdaki desen belgelerini kontrol etmeden ve (b) reddetme yorumunda teknik gerekçeyi kaydetmeden geçiştirmeyin. Örnek: `js/stack-trace-exposure` hatası, zaten `sanitizeErrorMessage()` üzerinden yönlendirilmiş çağrı noktalarında ortaya çıkmaktadır ve bu bilinen bir CodeQL sınırlamasıdır (özel temizleyiciler tanınmaz) — `docs/security/ERROR_SANITIZATION.md`'ye atıfta bulunarak `false positive` olarak reddedin.
15. Asla çocuk süreçleri başlatan rotaları (`/api/mcp/`, `/api/cli-tools/runtime/`) `src/server/authz/routeGuard.ts` içinde `isLocalOnlyPath()` sınıflandırması olmadan dahil etmeyin. Döngü geri uygulaması, herhangi bir kimlik doğrulama kontrolünden önce koşulsuz olarak gerçekleşir — tünel aracılığıyla sızdırılan JWT, süreç başlatmayı tetikleyemez. `docs/security/ROUTE_GUARD_TIERS.md`'ye bakın.
16. Asla AI asistanı, LLM veya otomasyon hesabını krediye alan `Co-Authored-By` ekleri içermeyin (örn. "Claude", "GPT", "Copilot", "Bot" içeren isimler; `anthropic.com` / `openai.com` / bot sahipli `noreply.github.com` adreslerindeki e-postalar). Bu tür ekler GitHub'da commit atfını bot hesabına yönlendirir ve PR geçmişinde gerçek yazarı (`diegosouzapw`) gizler. İnsan katkıda bulunanlar — upstream PR yazarları ve OmniRoute'a port edilen issue raporlayıcıları dahil — standart `Co-authored-by: Name <email>` ekleriyle krediye ALINABİLİR ve ALINMALIDIR; upstream-port iş akışları (`/port-upstream-features`, `/port-upstream-issues`) buna bağlıdır.
Bir dal açmadan veya PR oluşturmadan önce base-green kontrolünü çalıştırın (`AGENTS.md` → Git Workflow → "Base-green check"; proje yetenekleri bunu `.agents/skills/_shared/base-green.md` olarak referans alır). Temel uç (base tip) kırmızı iken açılan bir PR, gövdesinde `⚠️ base-red inherited: #<issue>` taşımalıdır. Birikmiş kırmızı durumu (temel uç + kırmızı PR'lar) boşaltmak için `/sweep-reds` yeteneğini kullanın.

View File

@@ -1,132 +1,88 @@
# Contributor Covenant Code of Conduct (Türkçe)
# Katılımcı Sözleşmesi Davranış Kuralları (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../CODE_OF_CONDUCT.md) · 🇸🇦 [ar](../ar/CODE_OF_CONDUCT.md) · 🇧🇬 [bg](../bg/CODE_OF_CONDUCT.md) · 🇧🇩 [bn](../bn/CODE_OF_CONDUCT.md) · 🇨🇿 [cs](../cs/CODE_OF_CONDUCT.md) · 🇩🇰 [da](../da/CODE_OF_CONDUCT.md) · 🇩🇪 [de](../de/CODE_OF_CONDUCT.md) · 🇪🇸 [es](../es/CODE_OF_CONDUCT.md) · 🇮🇷 [fa](../fa/CODE_OF_CONDUCT.md) · 🇫🇮 [fi](../fi/CODE_OF_CONDUCT.md) · 🇫🇷 [fr](../fr/CODE_OF_CONDUCT.md) · 🇮🇳 [gu](../gu/CODE_OF_CONDUCT.md) · 🇮🇱 [he](../he/CODE_OF_CONDUCT.md) · 🇮🇳 [hi](../hi/CODE_OF_CONDUCT.md) · 🇭🇺 [hu](../hu/CODE_OF_CONDUCT.md) · 🇮🇩 [id](../id/CODE_OF_CONDUCT.md) · 🇮🇹 [it](../it/CODE_OF_CONDUCT.md) · 🇯🇵 [ja](../ja/CODE_OF_CONDUCT.md) · 🇰🇷 [ko](../ko/CODE_OF_CONDUCT.md) · 🇮🇳 [mr](../mr/CODE_OF_CONDUCT.md) · 🇲🇾 [ms](../ms/CODE_OF_CONDUCT.md) · 🇳🇱 [nl](../nl/CODE_OF_CONDUCT.md) · 🇳🇴 [no](../no/CODE_OF_CONDUCT.md) · 🇵🇭 [phi](../phi/CODE_OF_CONDUCT.md) · 🇵🇱 [pl](../pl/CODE_OF_CONDUCT.md) · 🇵🇹 [pt](../pt/CODE_OF_CONDUCT.md) · 🇧🇷 [pt-BR](../pt-BR/CODE_OF_CONDUCT.md) · 🇷🇴 [ro](../ro/CODE_OF_CONDUCT.md) · 🇷🇺 [ru](../ru/CODE_OF_CONDUCT.md) · 🇸🇰 [sk](../sk/CODE_OF_CONDUCT.md) · 🇸🇪 [sv](../sv/CODE_OF_CONDUCT.md) · 🇰🇪 [sw](../sw/CODE_OF_CONDUCT.md) · 🇮🇳 [ta](../ta/CODE_OF_CONDUCT.md) · 🇮🇳 [te](../te/CODE_OF_CONDUCT.md) · 🇹🇭 [th](../th/CODE_OF_CONDUCT.md) · 🇹🇷 [tr](../tr/CODE_OF_CONDUCT.md) · 🇺🇦 [uk-UA](../uk-UA/CODE_OF_CONDUCT.md) · 🇵🇰 [ur](../ur/CODE_OF_CONDUCT.md) · 🇻🇳 [vi](../vi/CODE_OF_CONDUCT.md) · 🇨🇳 [zh-CN](../zh-CN/CODE_OF_CONDUCT.md)
---
## Our Pledge
## Taahhüdümüz
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
Topluluk üyeleri, katkıda bulunanlar ve liderler olarak; yaş, vücut ölçüsü, görünür veya görünmez engellilik, etnik köken, cinsiyet özellikleri, cinsiyet kimliği ve ifadesi, deneyim düzeyi, eğitim, sosyo-ekonomik durum, milliyet, kişisel görünüm, ırk, din veya cinsel kimlik ve yönelim gözetilmeksizin herkes için topluluğumuza katılımı tacizden uzak bir deneyim haline getirmeyi taahhüt ediyoruz.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
ık, sıcak, çeşitli, kapsayıcı ve sağlıklı bir topluluğa katkıda bulunacak şekilde davranmayı ve etkileşim kurmayı taahhüt ediyoruz.
## Our Standards
## Standartlarımız
Examples of behavior that contributes to a positive environment for our
community include:
Topluluğumuz için olumlu bir ortama katkıda bulunan davranış örnekleri şunlardır:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
- Diğer insanlara karşı empati ve nezaket göstermek
- Farklı görüşlere, bakış açılarına ve deneyimlere saygılı olmak
- Yapıcı geri bildirim vermek ve bunu olgunlukla kabul etmek
- Hatalarımızdan etkilenenlerden sorumluluk alıp özür dilemek ve bu deneyimden ders çıkarmak
- Sadece bireysel olarak bizim için değil, tüm topluluk için en iyi olana odaklanmak
Examples of unacceptable behavior include:
Kabul edilemez davranış örnekleri şunlardır:
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
- Cinselleştirilmiş dil veya görsellerin kullanımı ile her türlü cinsel ilgi veya yakınlaşma
- Trolleme, aşağılayıcı veya rencide edici yorumlar ve kişisel ya da politik saldırılar
- Kamuya açık veya özel alanda taciz
- ık izinleri olmadan başkalarının fiziksel adres veya e-posta adresi gibi özel bilgilerini yayımlamak
- Profesyonel bir ortamda makul olarak uygunsuz kabul edilebilecek diğer davranışlar
## Enforcement Responsibilities
## Uygulama Sorumlulukları
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Topluluk liderleri, kabul edilebilir davranış standartlarımızııklığa kavuşturmaktan ve uygulamaktan sorumludur; uygunsuz, tehdit edici, saldırgan veya zararlı gördükleri herhangi bir davranışa karşılık adil ve uygun düzeltici önlemleri alacaklardır.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
Topluluk liderleri, bu Davranış Kuralları ile uyumlu olmayan yorumları, commit'leri, kodları, wiki düzenlemelerini, issue'ları ve diğer katkıları kaldırma, düzenleme veya reddetme hakkına ve sorumluluğuna sahiptir ve uygun olduğunda moderasyon kararlarının gerekçelerini ileteceklerdir.
## Scope
## Kapsam
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
Bu Davranış Kuralları tüm topluluk alanlarında geçerlidir ve ayrıca bir birey topluluğu kamusal alanlarda resmi olarak temsil ettiğinde de geçerlidir. Topluluğumuzu temsil etme örnekleri arasında resmi bir e-posta adresi kullanmak, resmi bir sosyal medya hesabı aracılığıyla paylaşım yapmak veya çevrimiçi ya da çevrimdışı bir etkinlikte atanmış bir temsilci olarak hareket etmek yer alır.
## Enforcement
## Yaptırım
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.
İstismar edici, taciz edici veya başka bir şekilde kabul edilemez davranış durumları, yaptırımdan sorumlu topluluk liderlerine şu adresten özel bir güvenlik bildirimi (security advisory) açılarak bildirilebilir:
<https://github.com/diegosouzapw/OmniRoute/security/advisories/new>
veya proje yöneticisine diegosouza.pw@outlook.com adresinden e-posta gönderilebilir.
Güvenlikle ilgili hassas olaylar için bkz. [`SECURITY.md`](SECURITY.md).
Tüm şikayetler derhal ve adil bir şekilde incelenecek ve araştırılacaktır.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
Tüm topluluk liderleri, herhangi bir olayı bildiren kişinin gizliliğine ve güvenliğine saygı duymakla yükümlüdür.
## Enforcement Guidelines
## Yaptırım Yönergeleri
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
Topluluk liderleri, bu Davranış Kurallarını ihlal ettiğini düşündükleri herhangi bir eylemin sonuçlarını belirlerken aşağıdaki Topluluk Etki Yönergelerini izleyecektir:
### 1. Correction
### 1. Düzeltme
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Topluluk Etkisi**: Toplulukta uygunsuz veya profesyonellik dışı kabul edilen dil kullanımı veya diğer davranışlar.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
**Son**: Topluluk liderlerinden ihlalin niteliğini açıklayan ve davranışın neden uygunsuz olduğunu belirten özel, yazılı bir uyarı. Kamuya açık bir özür talep edilebilir.
### 2. Warning
### 2. Uyarı
**Community Impact**: A violation through a single incident or series
of actions.
**Topluluk Etkisi**: Tek bir olay veya bir dizi eylem yoluyla yapılan bir ihlal.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
**Son**: Davranışın devam etmesi durumunda doğacak sonuçları içeren bir uyarı. Belirli bir süre boyunca, Davranış Kurallarını uygulayan kişilerle talep edilmeyen etkileşimler de dahil olmak üzere, ilgili kişilerle hiçbir etkileşimde bulunulamaz. Buna topluluk alanlarının yanı sıra sosyal medya gibi harici kanallardaki etkileşimlerden kaçınmak da dahildir. Bu koşulların ihlali geçici veya kalıcı bir uzaklaştırmaya yol açabilir.
### 3. Temporary Ban
### 3. Geçici Uzaklaştırma
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Topluluk Etkisi**: Sürekli uygunsuz davranışlar da dahil olmak üzere topluluk standartlarının ciddi bir şekilde ihlali.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
**Son**: Belirli bir süre boyunca toplulukla her türlü etkileşimden veya kamusal iletişimden geçici olarak men edilme. Bu süre zarfında, Davranış Kurallarını uygulayan kişilerle talep edilmeyen etkileşimler de dahil olmak üzere, ilgili kişilerle kamuya açık veya özel hiçbir etkileşime izin verilmez. Bu koşulların ihlali kalıcı bir uzaklaştırmaya yol açabilir.
### 4. Permanent Ban
### 4. Kalıcı Uzaklaştırma
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Topluluk Etkisi**: Sürekli uygunsuz davranışlar, bir bireyin taciz edilmesi veya belirli insan gruplarına yönelik saldırganlık ya da aşağılama da dahil olmak üzere topluluk standartlarını sistematik olarak ihlal etme kalıbı sergilemek.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
**Son**: Topluluk içindeki her türlü kamusal etkileşimden kalıcı olarak men edilme.
## Attribution
## Kaynak ve Atıf
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Bu Davranış Kuralları, [Contributor Covenant][homepage] sürüm 2.1'den uyarlanmıştır; orijinaline şu adresten ulaşılabilir:
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
Topluluk Etki Yönergeleri, [Mozilla'nın davranış kuralları yaptırım merdiveninden](https://github.com/mozilla/diversity) esinlenmiştir.
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
Bu davranış kuralları hakkında sık sorulan soruların yanıtları için https://www.contributor-covenant.org/faq adresindeki SSS bölümüne bakın. Çeviriler https://www.contributor-covenant.org/translations adresinde mevcuttur.

View File

@@ -1,22 +1,30 @@
# Contributing to OmniRoute (Türkçe)
# OmniRoute'a Katkıda Bulunma (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../CONTRIBUTING.md) · 🇸🇦 [ar](../ar/CONTRIBUTING.md) · 🇧🇬 [bg](../bg/CONTRIBUTING.md) · 🇧🇩 [bn](../bn/CONTRIBUTING.md) · 🇨🇿 [cs](../cs/CONTRIBUTING.md) · 🇩🇰 [da](../da/CONTRIBUTING.md) · 🇩🇪 [de](../de/CONTRIBUTING.md) · 🇪🇸 [es](../es/CONTRIBUTING.md) · 🇮🇷 [fa](../fa/CONTRIBUTING.md) · 🇫🇮 [fi](../fi/CONTRIBUTING.md) · 🇫🇷 [fr](../fr/CONTRIBUTING.md) · 🇮🇳 [gu](../gu/CONTRIBUTING.md) · 🇮🇱 [he](../he/CONTRIBUTING.md) · 🇮🇳 [hi](../hi/CONTRIBUTING.md) · 🇭🇺 [hu](../hu/CONTRIBUTING.md) · 🇮🇩 [id](../id/CONTRIBUTING.md) · 🇮🇹 [it](../it/CONTRIBUTING.md) · 🇯🇵 [ja](../ja/CONTRIBUTING.md) · 🇰🇷 [ko](../ko/CONTRIBUTING.md) · 🇮🇳 [mr](../mr/CONTRIBUTING.md) · 🇲🇾 [ms](../ms/CONTRIBUTING.md) · 🇳🇱 [nl](../nl/CONTRIBUTING.md) · 🇳🇴 [no](../no/CONTRIBUTING.md) · 🇵🇭 [phi](../phi/CONTRIBUTING.md) · 🇵🇱 [pl](../pl/CONTRIBUTING.md) · 🇵🇹 [pt](../pt/CONTRIBUTING.md) · 🇧🇷 [pt-BR](../pt-BR/CONTRIBUTING.md) · 🇷🇴 [ro](../ro/CONTRIBUTING.md) · 🇷🇺 [ru](../ru/CONTRIBUTING.md) · 🇸🇰 [sk](../sk/CONTRIBUTING.md) · 🇸🇪 [sv](../sv/CONTRIBUTING.md) · 🇰🇪 [sw](../sw/CONTRIBUTING.md) · 🇮🇳 [ta](../ta/CONTRIBUTING.md) · 🇮🇳 [te](../te/CONTRIBUTING.md) · 🇹🇭 [th](../th/CONTRIBUTING.md) · 🇹🇷 [tr](../tr/CONTRIBUTING.md) · 🇺🇦 [uk-UA](../uk-UA/CONTRIBUTING.md) · 🇵🇰 [ur](../ur/CONTRIBUTING.md) · 🇻🇳 [vi](../vi/CONTRIBUTING.md) · 🇨🇳 [zh-CN](../zh-CN/CONTRIBUTING.md)
---
Thank you for your interest in contributing! This guide covers everything you need to get started.
Katkıda bulunmak istediğiniz için teşekkür ederiz! Bu kılavuz başlamak için ihtiyacınız olan her şeyi kapsar.
Değişiklik başına resmi iş akışı için [Katkı Altın Yolu (Contribution Golden Path)](docs/ops/CONTRIBUTION_GOLDEN_PATH.md) belgesiyle başlayın. Sağlayıcı, yönlendirme, UI/UX, i18n, CLI, veritabanı ve derleme/dağıtım değişikliklerini ilgili sözleşmelere, odaklanmış testlere, CI kapsamına ve mutabakat adımlarına eşler.
---
## Development Setup
## Geliştirme Ortamı Kurulumu
### Prerequisites
### Ön Koşullar
- **Node.js** >= 18 < 24 (recommended: 22 LTS)
- **Node.js** `>=22.22.3 <23` veya `>=24.0.0 <27` (önerilen: 24 LTS)
- **npm** 10+
> **npm v11+ kullanıcıları (Node 24+):** `npm install` sonrasında yerel modüllerin kurulduğunu doğrulayın:
> `node -e "require('better-sqlite3')"`. Eğer `MODULE_NOT_FOUND` hatası alırsanız,
> `npm approve-scripts better-sqlite3 && npm install` komutunu çalıştırın. Bkz.
> [Sorun Giderme](docs/guides/TROUBLESHOOTING.md#npm-v11-better-sqlite3-not-installed-cannot-find-module).
- **Git**
### Clone & Install
### Klonlama ve Kurulum
```bash
git clone https://github.com/diegosouzapw/OmniRoute.git
@@ -24,85 +32,117 @@ cd OmniRoute
npm install
```
### Environment Variables
### Ortam Değişkenleri
```bash
# Create your .env from the template
# Şablondan kendi .env dosyanızı oluşturun
cp .env.example .env
# Generate required secrets
# Gerekli gizli anahtarları oluşturun
echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
```
Key variables for development:
Geliştirme için temel değişkenler:
| Variable | Development Default | Description |
| Değişken | Geliştirme Varsayılanı | Açıklama |
| ---------------------- | ------------------------ | --------------------- |
| `PORT` | `20128` | Server port |
| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
| `JWT_SECRET` | (generate above) | JWT signing secret |
| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
| `APP_LOG_LEVEL` | `info` | Log verbosity level |
| `PORT` | `20128` | Sunucu portu |
| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Ön uç için temel URL |
| `JWT_SECRET` | (yukarıda oluşturulur) | JWT imzalama sırrı |
| `INITIAL_PASSWORD` | `CHANGEME` | İlk giriş parolası |
| `APP_LOG_LEVEL` | `info` | Günlük ayrıntı düzeyi |
### Dashboard Settings
### Pano Ayarları
The dashboard provides UI toggles for features that can also be configured via environment variables:
Pano, ortam değişkenleri aracılığıyla da yapılandırılabilen özellikler için arayüz anahtarları sunar:
| Setting Location | Toggle | Description |
| ------------------- | ------------------ | ------------------------------ |
| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
| Ayar Konumu | Anahtar | Açıklama |
| ------------------- | ------------------ | ------------------------------------- |
| Ayarlar → Gelişmiş | Hata Ayıklama Modu | İstek günlüklerini etkinleştirir (UI) |
| Ayarlar → Genel | Kenar Çubuğu Görünürlüğü | Kenar çubuğu bölümlerini göster/gizle |
These settings are stored in the database and persist across restarts, overriding env var defaults when set.
Bu ayarlar veritabanında saklanır ve yeniden başlatmalar arasında kalıcıdır; ayarlandıklarında ortam değişkeni varsayılanlarını geçersiz kılarlar.
### Running Locally
### Yerel Olarak Çalıştırma
```bash
# Development mode (hot reload)
# Geliştirme modu (hot reload)
npm run dev
# Production build
npm run build
# Üretim derlemesi
npm run build # next build → .build/next/ ardından assembleStandalone → dist/
npm run start
# Common port configuration
# Sürüm derlemesi (temiz yeniden derleme + HEAD nöbetçisi — dağıtım için gereklidir)
npm run build:release # rm -rf .build dist && build + dist/BUILD_SHA yazar
# Yaygın port yapılandırması
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
Default URLs:
### Derleme Çıktısı Düzeni
- **Dashboard**: `http://localhost:20128/dashboard`
| Dizin | İçerik | Takip Ediliyor mu? |
| --------- | ------------------------------------------------------------------------- | ------------------ |
| `src/` | Uygulama kaynak kodu (TypeScript / TSX) | Evet |
| `.build/` | Ara dosyalar — `next build` çıktısı (gitignored, `distDir = .build/next`) | Hayır |
| `dist/` | Dağıtılabilir paket — `assembleStandalone` tarafından toplanır (gitignored) | Hayır |
Derleme hattı tek geçişlidir:
```
npm run build
└─ next build → .build/next/standalone (Next.js çıktısı)
└─ assembleStandalone() (standalone + static + public + yerel varlıkları kopyalar)
└─ çıktı: dist/ (server.js, .next/static/, public/, node_modules/)
```
`npm run build:release` ek olarak önce her iki dizini de temizler ve dağıtım bütünlüğü nöbetçisi olarak
`dist/BUILD_SHA` (= `git rev-parse --short HEAD`) yazar.
> **VPS dağıtım notu:** uzak imaj dizini `/usr/lib/node_modules/omniroute/app/`
> değişmemiştir. Dağıtım yetenekleri `dist/` içeriğini rsync ile buraya aktarır.
> Yalnızca repo içi derleme çıktı yolu taşınmıştır (`app/` → `dist/`).
Varsayılan URL'ler:
- **Pano**: `http://localhost:20128/dashboard`
- **API**: `http://localhost:20128/v1`
---
## Git Workflow
## Git İş Akışı
> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
> ⚠️ **KESİNLİKLE doğrudan `main` dalına commit atmayın.** Her zaman özellik dalları (feature branch) kullanın.
>
> **PR hedefi:** aktif `release/vX.Y.Z` dalını hedefleyin (`main` değil). Dal başına sürüm + yayımlama anında etiket modeli için
> [`docs/ops/BRANCHING_MODEL.md`](docs/ops/BRANCHING_MODEL.md) belgesine bakın.
```bash
git checkout -b feat/your-feature-name
# ... make changes ...
git commit -m "feat: describe your change"
git push -u origin feat/your-feature-name
# Open a Pull Request on GitHub
# Aktif sürüm ucundan dal oluşturun (örnek: release/v3.8.49)
git fetch origin
git checkout -b feat/ozellik-adiniz origin/release/v3.8.49
# ... değişiklikleri yapın ...
git commit -m "feat: degisikliginizi aciklayin"
git push -u origin feat/ozellik-adiniz
# Hedef dal = release/v3.8.49 olacak şekilde Pull Request açın
```
### Branch Naming
### Dal Adlandırma
| Prefix | Purpose |
| ----------- | ------------------------- |
| `feat/` | New features |
| `fix/` | Bug fixes |
| `refactor/` | Code restructuring |
| `docs/` | Documentation changes |
| `test/` | Test additions/fixes |
| `chore/` | Tooling, CI, dependencies |
| Önek | Amaç |
| ----------- | ----------------------------------- |
| `feat/` | Yeni özellikler |
| `fix/` | Hata düzeltmeleri |
| `refactor/` | Kod yeniden yapılandırması |
| `docs/` | Dokümantasyon değişiklikleri |
| `test/` | Test ekleme/düzeltme |
| `chore/` | Araçlar, CI, bağımlılıklar |
### Commit Messages
### Commit Mesajları
Follow [Conventional Commits](https://www.conventionalcommits.org/):
[Conventional Commits](https://www.conventionalcommits.org/) standartlarını izleyin:
```
feat: add circuit breaker for provider calls
@@ -112,200 +152,248 @@ test: add observability unit tests
refactor(db): consolidate rate limit tables
```
Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
Kapsamlar (v3.8): `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`, `cloud-agent`, `guardrails`, `compression`, `auto-combo`, `resilience`, `providers`, `executors`, `translator`, `domain`, `authz`.
---
## Running Tests
## Testleri Çalıştırma
```bash
# All tests (unit + vitest + ecosystem + e2e)
# Tüm testler (unit + vitest + ecosystem + e2e)
npm run test:all
# Single test file (Node.js native test runner — most tests use this)
# Tek bir test dosyası (Node.js yerel test çalıştırıcısı — çoğu test bunu kullanır)
node --import tsx/esm --test tests/unit/your-file.test.ts
# Vitest (MCP server, autoCombo, cache)
# Vitest (MCP sunucusu, autoCombo, önbellek)
npm run test:vitest
# E2E tests (requires Playwright)
# E2E testleri (Playwright gerektirir)
npm run test:e2e
# Protocol clients E2E (MCP transports, A2A)
# Protokol istemcileri E2E (MCP tımaları, A2A)
npm run test:protocols:e2e
# Ecosystem compatibility tests
# Ekosistem uyumluluk testleri
npm run test:ecosystem
# Coverage (60% min statements/lines/functions/branches)
# Kapsam kapısı: %60 statements/lines/functions/branches
npm run test:coverage
npm run coverage:report
# Lint + format check
# Lint + biçimlendirme kontrolü
npm run lint
npm run check
# Gerçek yukarı akış kombo testi (VPS erişimi + gerçek sağlayıcı kredisi gerektirir)
# GERÇEK sağlayıcılara istek atar — küçük bir maliyeti vardır. CI'da ASLA çalışmaz.
RUN_COMBO_LIVE=1 npm run test:combo:live
# Aşama-3 VPS canlı testi — doğrudan canlı .15 sunucusuna istek atar.
npm run test:combo:live:vps # 7 HTTP senaryosu (priority/round-robin/weighted/cost/fusion/auto + health)
npm run test:combo:live:vps:failover # gerçek sağlayıcılar arası geçiş senaryosu ekler (toplam 8)
```
Coverage notes:
Test kapsamı notları:
- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
- Pull requests must keep the overall coverage gate at **60% or higher** for statements, lines, functions, and branches
- If a PR changes production code in `src/`, `open-sse/`, `electron/`, or `bin/`, it must add or update automated tests in the same PR
- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
- `npm run test:coverage:legacy` preserves the older metric for historical comparison
- See `docs/ops/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
- `npm run test:coverage` ana birim test paketi için kaynak kapsamını ölçer, `tests/**` dizinini hariç tutar ve `open-sse/**` dizinini dahil eder
- Pull Request'ler kapsam kapısını **%60+** (statements/lines/functions/branches) seviyesinde tutmalıdır
- Bir PR `src/`, `open-sse/`, `electron/` veya `bin/` altındaki üretim kodunu değiştiriyorsa, aynı PR'da otomatik testler eklemeli veya güncellemelidir
- `npm run coverage:report` en son test çalıştırmasından detaylı dosya bazlı raporu yazdırır
- Kademeli kapsam iyileştirme yol haritası için `docs/ops/COVERAGE_PLAN.md` dosyasına bakın
### Pull Request Requirements
### Pull Request Gereksinimleri
Before opening or merging a PR:
Bir PR açmadan önce, değiştirdiğiniz alan için odaklanmış döngüyü çalıştırmak üzere [Katkı Altın Yolu](docs/ops/CONTRIBUTION_GOLDEN_PATH.md) belgesini kullanın:
- Run `npm run test:unit`
- Run `npm run test:coverage`
- Ensure the coverage gate stays at **60%+** for all metrics
- Include the changed or added test files in the PR description when production code changed
- Check the SonarQube result on the PR when the project secrets are configured in CI
- Değişikliğinizi kapsayan test dosyalarını çalıştırın: `node --import tsx/esm --test tests/unit/<dosya>.test.ts`
- `npm run lint` çalıştırın
- Üretim kodu değiştiğinde her zaman aynı PR'a otomatik testler ekleyin veya güncelleyin
- Üretim kodu değiştiğinde PR açıklamasına değiştirilen veya eklenen test dosyalarını ekleyin
- CI'da proje sırları yapılandırıldığında PR üzerindeki SonarQube sonucunu kontrol edin
Current test status: **122 unit test files** covering:
Mevcut test durumu: **122 birim test dosyası** şunları kapsar:
- Provider translators and format conversion
- Rate limiting, circuit breaker, and resilience
- Semantic cache, idempotency, progress tracking
- Database operations and schema (21 DB modules)
- OAuth flows and authentication
- API endpoint validation (Zod v4)
- MCP server tools and scope enforcement
- Memory and Skills systems
- Sağlayıcı çevirmenleri ve format dönüştürme
- Hız sınırlaması, devre kesici ve dayanıklılık
- Anlamsal önbellek, tekilleştirme, ilerleme takibi
- Veritabanı işlemleri ve şeması (21 DB modülü)
- OAuth akışları ve kimlik doğrulama
- API uç noktası doğrulaması (Zod v4)
- MCP sunucu araçları ve kapsam denetimi
- Bellek ve Yetenek (Skills) sistemleri
---
## Code Style
## Kod Stili
- **ESLint** — Run `npm run lint` before committing
- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
- **Zod validation** — Use Zod v4 schemas for all API input validation
- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
- **ESLint** — Commit öncesinde `npm run lint` çalıştırın
- **Prettier** — Commit sırasında `lint-staged` aracılığıyla otomatik biçimlendirilir (2 boşluk, noktalı virgül, çift tırnak, 100 karakter genişlik, es5 son virgüller)
- **TypeScript** — Tüm `src/` kodu `.ts`/`.tsx` kullanır; `open-sse/` `.ts`/`.js` kullanır; TSDoc (`@param`, `@returns`, `@throws`) ile belgeleyin
- **`eval()` Yasaktır** — ESLint `no-eval`, `no-implied-eval`, `no-new-func` kurallarını zorunlu kılar
- **Zod doğrulaması** — Tüm API girdi doğrulamaları için Zod v4 şemalarını kullanın
- **Adlandırma**: Dosyalar = camelCase/kebab-case, bileşenler = PascalCase, sabitler = UPPER_SNAKE
### Hata Yönetimi / Boş Catch Blokları
Bir `catch` bloğunu asla açıklamasız bırakmayın. İki kategoriden birine ayırın:
- **Kasıtlı (kendi en iyi çaba temizliğimiz/telemetrimiz)** — burada bir hata beklenir ve zararsızdır; tek satırlık bir gerekçe yorumu ekleyin, günlük kaydı yapmayın:
```ts
} catch {} // istemci bağlantısı kesildikten sonra zaten kapalı bir denetleyiciyi kapatmak beklenen bir durumdur
```
- **Günlüğe kaydedilmeli (harici kod veya akışı değiştiren durumlar)** — catch'i koruyun ancak hatanın keşfedilebilmesi için bağlamsal bir `console.debug`/`warn` yayınlayın:
```ts
} catch (e) {
console.debug("[STREAM] onFailure callback error:", e);
}
```
Uygulamalı örnekler için `open-sse/utils/stream.ts` ve `open-sse/utils/streamHandler.ts` dosyalarına bakın.
---
## Project Structure
## Proje Yapısı
```
src/ # TypeScript (.ts / .tsx)
├── app/ # Next.js 16 App Router
│ ├── (dashboard)/ # Dashboard pages (23 sections)
│ ├── api/ # API routes (51 directories)
│ └── login/ # Auth pages (.tsx)
├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
├── lib/ # Core business logic (.ts)
│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
│ ├── acp/ # Agent Communication Protocol registry
│ ├── compliance/ # Compliance policy engine
│ ├── db/ # SQLite database layer (110 top-level modules + 130 migrations)
│ ├── memory/ # Persistent conversational memory
│ ├── oauth/ # OAuth providers, services, and utilities
│ ├── skills/ # Extensible skill framework
│ ├── usage/ # Usage tracking and cost calculation
│ └── localDb.ts # Re-export layer only — never add logic here
├── middleware/ # Request middleware (promptInjectionGuard)
├── mitm/ # MITM proxy (cert, DNS, target routing)
│ ├── (dashboard)/ # Pano sayfaları (23 bölüm)
│ ├── api/ # API rotaları (51 dizin)
│ └── login/ # Kimlik doğrulama sayfaları (.tsx)
├── domain/ # Politika motoru (policyEngine, comboResolver, costRules, vb.)
├── lib/ # Çekirdek iş mantığı (.ts)
│ ├── a2a/ # Agent-to-Agent v0.3 protokol sunucusu
│ ├── acp/ # Ajan İletişim Protokolü kayıt defteri
│ ├── compliance/ # Uyumluluk politika motoru
│ ├── db/ # SQLite alan modülleri + 130 migrasyon
│ ├── memory/ # Kalıcı konuşma belleği
│ ├── oauth/ # OAuth sağlayıcıları, servisleri ve yardımcıları
│ ├── skills/ # Genişletilebilir yetenek çerçevesi
│ ├── usage/ # Kullanım takibi ve maliyet hesaplama
│ └── localDb.ts # Yalnızca yeniden dışa aktarma katmanı — buraya asla mantık eklemeyin
├── middleware/ # İstek ara yazılımı (promptInjectionGuard)
├── mitm/ # MITM proxy (sertifika, DNS, hedef yönlendirme)
├── shared/
│ ├── components/ # React components (.tsx)
│ ├── constants/ # Provider definitions (329), MCP scopes, routing strategies
│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
│ └── validation/ # Zod v4 schemas
└── sse/ # SSE proxy pipeline
│ ├── components/ # React bileşenleri (.tsx)
│ ├── constants/ # Sağlayıcı tanımları (329), MCP kapsamları, 19 yönlendirme stratejisi
│ ├── utils/ # Devre kesici, temizleyici, kimlik doğrulama yardımcıları
│ └── validation/ # Zod v4 şemaları
└── sse/ # SSE proxy hattı
open-sse/ # @omniroute/open-sse workspace
├── executors/ # 89 executor implementation modules
├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
├── mcp-server/ # MCP server (107 tools, 3 transports, 32 scopes)
├── services/ # 178 top-level services (combo, autoCombo, rateLimitManager, etc.)
├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
├── transformer/ # Responses API transformer
└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
open-sse/ # @omniroute/open-sse çalışma alanı
├── executors/ # 89 yürütücü uygulama modülü
├── handlers/ # 11 istek işleyici (chat, responses, embeddings, images, vb.)
├── mcp-server/ # MCP sunucusu (107 benzersiz araç, 3 taşıma, 32 kapsam)
├── services/ # 178 üst düzey servis (combo, autoCombo, rateLimitManager, vb.)
├── translator/ # Format çevirmenleri (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
├── transformer/ # Responses API dönüştürücüsü
└── utils/ # 22 yardımcı modül (stream, TLS, proxy, logging)
electron/ # Electron desktop app (cross-platform)
electron/ # Electron masaüstü uygulaması (platformlar arası)
tests/
├── unit/ # Node.js test runner (122 test files)
├── integration/ # Integration tests
├── e2e/ # Playwright tests
├── security/ # Security tests
├── translator/ # Translator-specific tests
└── load/ # Load tests
├── unit/ # Node.js test çalıştırıcısı (1.574 test dosyası)
├── integration/ # Entegrasyon testleri
├── e2e/ # Playwright testleri
├── security/ # Güvenlik testleri
├── translator/ # Çevirmene özel testler
└── load/ # Yük testleri
docs/ # Documentation
├── ARCHITECTURE.md # System architecture
├── API_REFERENCE.md # All endpoints
├── USER_GUIDE.md # Provider setup, CLI integration
├── TROUBLESHOOTING.md # Common issues
├── MCP-SERVER.md # MCP server (107 tools)
├── A2A-SERVER.md # A2A agent protocol
├── AUTO-COMBO.md # Auto-combo engine
├── CLI-TOOLS.md # CLI tools integration
├── COVERAGE_PLAN.md # Test coverage improvement plan
├── openapi.yaml # OpenAPI specification
── adr/ # Architecture Decision Records
docs/
├── adr/ # Mimari Karar Kayıtları (ADR)
├── architecture/ # Sistem mimarisi ve dayanıklılık
├── comparison/ # OmniRoute ve alternatifler
├── compression/ # Sıkıştırma kılavuzları ve kuralları
├── dev/ # Geliştirme kılavuzları
├── diagrams/ # Mimari diyagramları
├── frameworks/ # MCP, A2A, OpenCode, Bellek, Yetenekler
├── guides/ # Kullanıcı kılavuzu, Docker, kurulum, sorun giderme
├── i18n/ # Çok dilli README çevirileri
├── marketing/ # Pazarlama materyalleri
── ops/ # Dağıtım, proxy, test kapsamı, sürümler
├── providers/ # Sağlayıcıya özel belgeler
├── reference/ # API referansı, ortam değişkenleri, CLI araçları, ücretsiz katmanlar
├── releases/ # Sürüm notları
├── routing/ # Auto-combo motoru, akıl yürütme tekrarı
├── screenshots/ # Pano ekran görüntüleri
├── security/ # Güvenlik önlemleri, uyumluluk, gizlilik, belirteçler
└── specs/ # Tasarım özellikleri
```
---
## Adding a New Provider
## Yeni Bir Sağlayıcı Ekleme
### Step 1: Register Provider Constants
### Adım 1: Sağlayıcı Sabitlerini Kaydedin
Add to `src/shared/constants/providers.ts`Zod-validated at module load.
`src/shared/constants/providers.ts` dosyasına ekleyinmodül yükleme sırasında Zod ile doğrulanır.
### Step 2: Add Executor (if custom logic needed)
### Adım 2: Yürütücü (Executor) Ekleyin (özel mantık gerekiyorsa)
Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
`open-sse/executors/your-provider.ts` içinde temel yürütücüyü genişleten bir yürütücü oluşturun.
### Step 3: Add Translator (if non-OpenAI format)
### Adım 3: Çevirmen (Translator) Ekleyin (OpenAI dışı format ise)
Create request/response translators in `open-sse/translator/`.
`open-sse/translator/` altında istek/yanıt çevirmenleri oluşturun.
### Step 4: Add OAuth Config (if OAuth-based)
### Adım 4: OAuth Yapılandırması Ekleyin (OAuth tabanlıysa)
Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
`src/lib/oauth/constants/oauth.ts` içine OAuth kimlik bilgilerini ve `src/lib/oauth/services/` içine servisini ekleyin.
### Step 5: Register Models
Yukarı akış sağlayıcısı genel bir OAuth client_id/secret veya Firebase Web API anahtarı dağıtıyorsa, bunu kaynak koda **dize sabiti olarak gömmeyin**. `open-sse/utils/publicCreds.ts` dosyasındaki `resolvePublicCred()` fonksiyonunu kullanın ve `EMBEDDED_DEFAULTS` içine maskelenmiş bayt girişi ekleyin. Zorunlu iş akışı [`docs/security/PUBLIC_CREDS.md`](docs/security/PUBLIC_CREDS.md) içinde belgelenmiştir.
Add model definitions in `open-sse/config/providerRegistry.ts`.
İşleyiciler/yürütücüler içinde istemciye ulaşan hata mesajları `open-sse/utils/error.ts` içindeki `buildErrorBody()` / `sanitizeErrorMessage()` üzerinden geçmelidir — Response gövdesine asla ham `err.stack` veya `err.message` koymayın. Bkz. [`docs/security/ERROR_SANITIZATION.md`](docs/security/ERROR_SANITIZATION.md).
### Step 6: Add Tests
### Adım 5: Modelleri Kaydedin
Write unit tests in `tests/unit/` covering at minimum:
`open-sse/config/providerRegistry.ts` dosyasına model tanımlarını ekleyin.
- Provider registration
- Request/response translation
- Error handling
### Adım 6: Testleri Ekleyin
`tests/unit/` altında en az şunları kapsayan birim testleri yazın:
- Sağlayıcı kaydı
- İstek/yanıt çevirisi
- Hata yönetimi
---
## Pull Request Checklist
## Pull Request Kontrol Listesi
- [ ] Tests pass (`npm test`)
- [ ] Linting passes (`npm run lint`)
- [ ] Build succeeds (`npm run build`)
- [ ] TypeScript types added for new public functions and interfaces
- [ ] No hardcoded secrets or fallback values
- [ ] All inputs validated with Zod schemas
- [ ] CHANGELOG updated (if user-facing change)
- [ ] Documentation updated (if applicable)
- [ ] Testler geçiyor (`npm test`)
- [ ] Linting geçiyor (`npm run lint`)
- [ ] Derleme başarılı (`npm run build`)
- [ ] Yeni genel fonksiyonlar ve arayüzler için TypeScript tipleri eklendi
- [ ] Sabit kodlanmış sırlar veya geri dönüş değerleri yok
- [ ] Genel yukarı akış kimlik bilgileri `resolvePublicCred()` ile eklendi ([`docs/security/PUBLIC_CREDS.md`](docs/security/PUBLIC_CREDS.md)), asla sabit dize olarak değil
- [ ] Hata yanıtları `buildErrorBody()` / `sanitizeErrorMessage()` üzerinden geçiyor — yanıt gövdelerinde ham yığın izi (stack trace) yok ([`docs/security/ERROR_SANITIZATION.md`](docs/security/ERROR_SANITIZATION.md))
- [ ] Kabuk komutları (`exec` / `spawn`) çalışma zamanı değerlerini dize birleştirme ile değil `env` ile iletiyor
- [ ] Tüm girdiler Zod şemaları ile doğrulanıyor
- [ ] Kullanıcıya yönelik değişiklikler için `changelog.d/{features|fixes|maintenance}/<PR>-<slug>.md` altında değişiklik günlüğü parçacığı (fragment) eklendi ([`changelog.d/README.md`](changelog.d/README.md)) — doğrudan `CHANGELOG.md` dosyasını düzenlemeyin
- [ ] Dokümantasyon güncellendi (varsa)
- [ ] Yeni CodeQL / Secret-Scanning uyarısıılmadı veya her biri ilgili `docs/security/` belgesine atıfta bulunarak teknik gerekçeyle kapatıldı
- [ ] Alt süreçler başlatan rotalar (`/api/mcp/`, `/api/cli-tools/runtime/`) `src/server/authz/routeGuard.ts` içinde `isLocalOnlyPath()` olarak sınıflandırıldı
- [ ] Commit mesajlarında `Co-Authored-By` bulunmuyor — commit'ler yalnızca depo sahibinin Git kimliği altında görünmelidir
---
## Releasing
## Sürüm Yayımlama
Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
Sürümler `/generate-release` iş akışı aracılığıyla yönetilir. Yeni bir GitHub Sürümü oluşturulduğunda, paket GitHub Actions aracılığıyla **otomatik olarak npm'de yayımlanır**.
VPS dağıtımları için `npm run build:release` kullanın — temiz bir yeniden derleme gerçekleştirir, paketi `dist/` içine toplar ve `dist/BUILD_SHA` nöbetçisini yazar. Ardından `dist/` dizinini uzak `app/` dizinine rsync eden `/deploy-vps-*-cc` yeteneklerini kullanın.
---
## Getting Help
## Yardım Alma
- **Architecture**: See [`docs/architecture/ARCHITECTURE.md`](docs/architecture/ARCHITECTURE.md)
- **API Reference**: See [`docs/reference/API_REFERENCE.md`](docs/reference/API_REFERENCE.md)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **ADRs**: See `docs/adr/` for architectural decision records
- **Mimari**: Bkz. [`docs/architecture/ARCHITECTURE.md`](docs/architecture/ARCHITECTURE.md)
- **API Referansı**: Bkz. [`docs/reference/API_REFERENCE.md`](docs/reference/API_REFERENCE.md)
- **Güvenlik belgeleri**: [`docs/security/CLI_TOKEN.md`](docs/security/CLI_TOKEN.md), [`docs/security/ROUTE_GUARD_TIERS.md`](docs/security/ROUTE_GUARD_TIERS.md), [`docs/security/ERROR_SANITIZATION.md`](docs/security/ERROR_SANITIZATION.md), [`docs/security/PUBLIC_CREDS.md`](docs/security/PUBLIC_CREDS.md)
- **Operasyon belgeleri**: [`docs/ops/SQLITE_RUNTIME.md`](docs/ops/SQLITE_RUNTIME.md)
- **Sorun Bildirimi (Issues)**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **Mimari Karar Kayıtları (ADR)**: Mimari karar kayıtları için `docs/adr/` dizinine bakın

View File

@@ -1,25 +1,12 @@
# Security and Cleanliness Rules for AI Assistants (Türkçe)
# GEMINI.md (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../GEMINI.md) · 🇸🇦 [ar](../ar/GEMINI.md) · 🇧🇬 [bg](../bg/GEMINI.md) · 🇧🇩 [bn](../bn/GEMINI.md) · 🇨🇿 [cs](../cs/GEMINI.md) · 🇩🇰 [da](../da/GEMINI.md) · 🇩🇪 [de](../de/GEMINI.md) · 🇪🇸 [es](../es/GEMINI.md) · 🇮🇷 [fa](../fa/GEMINI.md) · 🇫🇮 [fi](../fi/GEMINI.md) · 🇫🇷 [fr](../fr/GEMINI.md) · 🇮🇳 [gu](../gu/GEMINI.md) · 🇮🇱 [he](../he/GEMINI.md) · 🇮🇳 [hi](../hi/GEMINI.md) · 🇭🇺 [hu](../hu/GEMINI.md) · 🇮🇩 [id](../id/GEMINI.md) · 🇮🇹 [it](../it/GEMINI.md) · 🇯🇵 [ja](../ja/GEMINI.md) · 🇰🇷 [ko](../ko/GEMINI.md) · 🇮🇳 [mr](../mr/GEMINI.md) · 🇲🇾 [ms](../ms/GEMINI.md) · 🇳🇱 [nl](../nl/GEMINI.md) · 🇳🇴 [no](../no/GEMINI.md) · 🇵🇭 [phi](../phi/GEMINI.md) · 🇵🇱 [pl](../pl/GEMINI.md) · 🇵🇹 [pt](../pt/GEMINI.md) · 🇧🇷 [pt-BR](../pt-BR/GEMINI.md) · 🇷🇴 [ro](../ro/GEMINI.md) · 🇷🇺 [ru](../ru/GEMINI.md) · 🇸🇰 [sk](../sk/GEMINI.md) · 🇸🇪 [sv](../sv/GEMINI.md) · 🇰🇪 [sw](../sw/GEMINI.md) · 🇮🇳 [ta](../ta/GEMINI.md) · 🇮🇳 [te](../te/GEMINI.md) · 🇹🇭 [th](../th/GEMINI.md) · 🇹🇷 [tr](../tr/GEMINI.md) · 🇺🇦 [uk-UA](../uk-UA/GEMINI.md) · 🇵🇰 [ur](../ur/GEMINI.md) · 🇻🇳 [vi](../vi/GEMINI.md) · 🇨🇳 [zh-CN](../zh-CN/GEMINI.md)
---
## 1. File Placement & Organization
> **Tek doğruluk kaynağı:** Yapay zeka asistanları için tüm proje kuralları [`AGENTS.md`](AGENTS.md) dosyasında yer almaktadır. Herhangi bir değişiklik yapmadan önce tamamını okuyun — 23 Katı Kuralı, kalite kapılarını, kod kurallarını, dosya yerleşimi / depo kökü hijyen kurallarını, depo haritasını ve daha önce bu dosyada bulunan yerel geliştirme erişim notlarını içerir.
- **Test Files**: ALL unit tests, integration tests, ecosystem tests, or Vitest files MUST strictly be placed within the `tests/` directory (e.g., `tests/unit/`, `tests/integration/`). NEVER create test files in the project root (`/`).
- **Scripts and Utilities**: ALL maintenance, debugging, generation, or experimental scripts (`.cjs`, `.mjs`, `.js`, `.ts`) MUST be placed strictly inside the `scripts/` directory or `scripts/scratch/` for temporary one-offs. NEVER dump loose scripts in the project root (`/`).
Gemini'ye özel notlar:
**The Project Root MUST ONLY CONTAIN:**
- Configuration files (`vitest.config.ts`, `next.config.mjs`, `eslint.config.mjs`, etc.)
- Dependency files (`package.json`, `package-lock.json`)
- Documentation files (`README.md`, `CHANGELOG.md`, `AGENTS.md`)
- CI/CD files and ignore definitions (`.gitignore`, `.dockerignore`)
When creating _any_ validation tests or one-off logic scripts, default to using `scripts/scratch/` or the `tests/unit/` directories according to your goals. Do not pollute the `/` root context.
## 2. VPS Dashboard Credentials
| Environment | URL | Password |
| ----------- | ------------------------- | -------- |
| Local VPS | http://192.168.0.15:20128 | 123456 |
- Yetenekler (Skills), `activate_skill` aracı aracılığıyla etkinleştirilir (yetenek meta verileri oturum başlangıcında yüklenir ve tam içerik talep üzerine etkinleştirilir).
- Bugün için Gemini'ye özel başka bir kural yoktur. Buraya yeniden proje kuralları eklemeyin — her asistanın aynı talimatları görmesi için `AGENTS.md` dosyasını düzenleyin.

File diff suppressed because it is too large Load Diff

View File

@@ -1,159 +1,184 @@
# Security Policy (Türkçe)
# Güvenlik Politikası (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇧🇩 [bn](../bn/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇮🇷 [fa](../fa/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇮🇳 [gu](../gu/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇮🇳 [hi](../hi/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇮🇳 [mr](../mr/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇰🇪 [sw](../sw/SECURITY.md) · 🇮🇳 [ta](../ta/SECURITY.md) · 🇮🇳 [te](../te/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇹🇷 [tr](../tr/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇵🇰 [ur](../ur/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md)
---
## Reporting Vulnerabilities
## Güvenlik Açıklarını Bildirme
If you discover a security vulnerability in OmniRoute, please report it responsibly:
OmniRoute'ta bir güvenlik açığı keşfederseniz, lütfen sorumlu bir şekilde bildirin:
1. **DO NOT** open a public GitHub issue
2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
3. Include: description, reproduction steps, and potential impact
1. **KESİNLİKLE** herkese açık bir GitHub issue'su açmayın
2. [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new) kullanın
3. Şunları ekleyin: açıklama, yeniden oluşturma adımları ve olası etki
## Response Timeline
## Yanıt Zaman Çizelgesi
| Stage | Target |
| ------------------- | --------------------------- |
| Acknowledgment | 48 hours |
| Triage & Assessment | 5 business days |
| Patch Release | 14 business days (critical) |
| Aşama | Hedef Süre |
| --------------------- | --------------------------- |
| İlk Bildirim Teyidi | 48 saat |
| Ön İnceleme ve Değerlendirme | 5 iş günü |
| Yama Sürümü (Patch) | 14 iş günü (kritik) |
## Supported Versions
## Desteklenen Sürümler
| Version | Support Status |
| Sürüm | Destek Durumu |
| ------- | -------------- |
| 3.6.x | ✅ Active |
| 3.5.x | ✅ Security |
| < 3.5.0 | ❌ Unsupported |
| 3.8.x | ✅ Aktif |
| 3.7.x | ✅ Güvenlik |
| < 3.7.0 | ❌ Desteklenmiyor |
---
## Security Architecture
## Güvenlik Mimarisi
OmniRoute implements a multi-layered security model:
OmniRoute çok katmanlı bir güvenlik modeli uygular:
```
Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
Request → CORS → Authz pipeline (classify → policies → enforce)
→ Guardrails (PII masker, prompt injection, vision bridge)
→ Rate Limiter → Circuit Breaker → Cooldown → Model Lockout → Provider
```
### 🔐 Authentication & Authorization
### 🔐 Kimlik Doğrulama ve Yetkilendirme
| Feature | Implementation |
| -------------------- | ---------------------------------------------------------- |
| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
| **API Key Auth** | HMAC-signed keys with CRC validation |
| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
| **Token Refresh** | Automatic OAuth token refresh before expiry |
| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
| **MCP Scopes** | 32 granular scopes for MCP tool access control |
| Özellik | Uygulama |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| **Pano Girişi** | JWT belirteçleri ile parola tabanlı kimlik doğrulama (HttpOnly çerezler) |
| **API Anahtarı Doğrulaması** | CRC doğrulamalı HMAC imzalı anahtarlar |
| **OAuth 2.0 + PKCE** | Sağlayıcıya özel tarayıcı/cihaz OAuth'u desteklenen yerlerde PKCE kullanır; yalnızca içe aktarılan Devin kimlik bilgileri ayrı işlenir. |
| **Belirteç Yenileme** | Süresi dolmadan önce otomatik OAuth belirteci yenileme |
| **Güvenli Çerezler** | HTTPS ortamları için `AUTH_COOKIE_SECURE=true` |
| **Yetkilendirme Hattı** | Rota sınıflandırması (PUBLIC / CLIENT_API / MANAGEMENT) — bkz. `docs/architecture/AUTHZ_GUIDE.md` |
| **Rota Koruma Katmanları** | Yönetim rotaları için 3 katmanlı model (LOCAL_ONLY / ALWAYS_PROTECTED / MANAGEMENT) — bkz. `docs/security/ROUTE_GUARD_TIERS.md` |
| **Yönetim Kapsamlı MCP** | `manage` kapsamına sahip API anahtarlarıyla korunan uzak `/api/mcp/*` erişimi; `/api/cli-tools/runtime/*` katı yerel döngüde kalır. |
| **MCP Kapsamları** | 32 ayrıntılı kapsam (read:health, write:combos, execute:completions vb.) — bkz. `docs/frameworks/MCP-SERVER.md` |
### 🛡️ Encryption at Rest
### 🛡️ Dinlenmede Şifreleme (Encryption at Rest)
All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
SQLite'ta saklanan tüm hassas veriler, scrypt anahtar türetme ile **AES-256-GCM** kullanılarak şifrelenir:
- API keys, access tokens, refresh tokens, and ID tokens
- Versioned format: `enc:v1:<iv>:<ciphertext>:<authTag>`
- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
- API anahtarları, erişim belirteçleri, yenileme belirteçleri ve ID belirteçleri
- Sürümlendirilmiş format: `enc:v1:<iv>:<ciphertext>:<authTag>`
- `STORAGE_ENCRYPTION_KEY` ayarlanmadığında doğrudan geçiş modu (düz metin)
```bash
# Generate encryption key:
# Şifreleme anahtarı oluşturun:
STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
```
### 🧠 Prompt Injection Guard
### 🛡️ Güvenlik Önlemleri Çerçevesi (Guardrails Framework)
Middleware that detects and blocks prompt injection attacks in LLM requests:
OmniRoute, öncelik sırasına göre sıralanmış 3 yerleşik güvenlik önlemi içeren, çalışırken yeniden yüklenebilir bir **güvenlik önlemleri kayıt defteri** (`src/lib/guardrails/`) ile gelir:
| Pattern Type | Severity | Example |
| ------------------- | -------- | ---------------------------------------------- |
| System Override | High | "ignore all previous instructions" |
| Role Hijack | High | "you are now DAN, you can do anything" |
| Delimiter Injection | Medium | Encoded separators to break context boundaries |
| DAN/Jailbreak | High | Known jailbreak prompt patterns |
| Instruction Leak | Medium | "show me your system prompt" |
| Güvenlik Önlemi | Öncelik | Amaç |
| ------------------ | ------- | --------------------------------------------------------------------------------------- |
| `vision-bridge` | 5 | Vision desteği olmayan modelleri görüntü açıklamalarıyla destekler; görsel URL'leri için SSRF koruması sağlar |
| `pii-masker` | 10 | Çağrı öncesi ve sonrası PII (kişisel veri) maskeleme (e-posta, telefon, CPF, CNPJ, kredi kartı, SSN) |
| `prompt-injection` | 20 | Geçersiz kılma / rol ele geçirme / jailbreak / sızıntı kalıplarını algılar |
Configure via dashboard (Settings → Security) or `.env`:
Özel güvenlik önlemleri `registerGuardrail(new MyGuardrail())` aracılığıyla kaydedilir. Model hata durumunda açıktır (fail-open; istisnalar trafiği asla engellemez). İstek başına devre dışı bırakma `x-omniroute-disabled-guardrails` başlığı ile yapılır. → Bkz. [`docs/security/GUARDRAILS.md`](docs/security/GUARDRAILS.md).
### 🧠 İstem Enjeksiyonu Koruması (Prompt Injection Guard)
LLM isteklerindeki istem enjeksiyonu modellerini algılayan en iyi çaba (heuristic) ara yazılımıdır.
**Eksiksiz bir istem enjeksiyonu güvenlik duvarı değildir** — yanlış pozitifler (zararsız
persona/RPG istemleri) ve yanlış negatifler (leetspeak, boşluk manipülasyonu, İngilizce dışı kalıplar) üretebilir.
| Kalıp Türü | Önem Derecesi | Örnek |
| ------------------- | ------------- | ---------------------------------------------- |
| Sistem Geçersiz Kılma | Yüksek (High) | "ignore all previous instructions" |
| Rol Ele Geçirme | Orta (Medium) | "you are now DAN, you can do anything" |
| Ayırıcı Enjeksiyonu | Yüksek (High) | Bağlam sınırlarını kırmak için kodlanmış ayırıcılar |
| DAN / Jailbreak | Orta (Medium) | Bilinen jailbreak istem kalıpları |
| Talimat Sızıntısı | Yüksek (High) | "show me your system prompt" |
| Kodlama Kaçırma | Orta (Medium) | base64/rot13/hex kod çözme + talimat anahtar kelimeleri |
`block` modunda yalnızca **High (Yüksek)** önem derecesindeki tespitler engellenir. Orta önem derecesindeki
aileler günlüğe kaydedilir ancak `sanitizeRequest` tarafından asla engellenmez.
Pano (Ayarlar → Güvenlik) veya `.env` üzerinden yapılandırın:
```env
INPUT_SANITIZER_ENABLED=true
INPUT_SANITIZER_MODE=block # warn | block | redact
INPUT_SANITIZER_MODE=block # warn | block (enjeksiyon politikası; eski "redact" modu enjeksiyon metnini silmez)
INPUT_SANITIZER_BLOCK_THRESHOLD=high # high (varsayılan) | medium | low — block modunda bu seviye ve üstü engellenir
```
### 🔒 PII Redaction
### 🔒 PII (Kişisel Veri) Maskeleme
Automatic detection and optional redaction of personally identifiable information:
Kişisel olarak tanımlanabilir bilgilerin otomatik olarak algılanması ve isteğe bağlı olarak maskelenmesi:
| PII Type | Pattern | Replacement |
| PII Türü | Kalıp | Değiştirilen Değer |
| ------------- | --------------------- | ------------------ |
| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
| E-posta | `user@domain.com` | `[EMAIL_REDACTED]` |
| CPF (Brezilya)| `123.456.789-00` | `[CPF_REDACTED]` |
| CNPJ (Brezilya)| `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
| Kredi Kartı | `4111-1111-1111-1111` | `[CC_REDACTED]` |
| Telefon | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
| SSN (ABD) | `123-45-6789` | `[SSN_REDACTED]` |
```env
PII_REDACTION_ENABLED=true
PII_REDACTION_ENABLED=true # istek PII yeniden yazımı; INPUT_SANITIZER_MODE'dan bağımsızdır
PII_RESPONSE_SANITIZATION=true # isteğe bağlı: istemcilere döndürülen sağlayıcı yanıtlarındaki PII'yi maskeler
```
### 🌐 Network Security
### 🌐 Ağ Güvenliği
| Feature | Description |
| ------------------------ | ---------------------------------------------------------------- |
| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
| **Rate Limiting** | Per-provider rate limits with automatic backoff |
| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
| Özellik | ıklama |
| ------------------------ | ------------------------------------------------------------------------------ |
| **CORS** | ık kaynaklar arası izin listesi (`CORS_ALLOWED_ORIGINS`; eski `CORS_ORIGIN`) |
| **IP Filtreleme** | Panoda IP aralıklarını izin listesine / engelleme listesine alma |
| **Hız Sınırlaması** | Otomatik geri çekilme ile sağlayıcı başına hız sınırları |
| **Sürü Önleme (Anti-Thundering Herd)** | Mutex + bağlantı başına kilitleme ile basamaklı 502 hatalarını önler |
| **TLS Parmak İzi** | Bot algılamasını azaltmak için tarayıcı benzeri TLS parmak izi taklidi |
| **CLI Parmak İzi** | Yerel CLI imzalarıyla eşleşmesi için sağlayıcı başına başlık/gövde sıralaması |
### 🔌 Resilience & Availability
### 🔌 Dayanıklılık ve Erişilebilirlik
| Feature | Description |
| Özellik | ıklama |
| ----------------------- | ------------------------------------------------------------------ |
| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
| **Request Idempotency** | 5-second dedup window for duplicate requests |
| **Exponential Backoff** | Automatic retry with increasing delays |
| **Health Dashboard** | Real-time provider health monitoring |
| **Devre Kesici (Circuit Breaker)** | Sağlayıcı başına 3 durumlu (Kapalı → Açık → Yarıık), SQLite ile kalıcı |
| **İstek Tekilleştirme** | Yinelenen istekler için 5 saniyelik tekilleştirme penceresi |
| **Üstel Geri Çekilme** | Artan gecikmelerle otomatik yeniden deneme |
| **Sağlık Panosu** | Gerçek zamanlı sağlayıcı sağlığı izleme |
### 📋 Compliance
### 📋 Uyumluluk (Compliance)
| Feature | Description |
| Özellik | ıklama |
| ------------------ | ----------------------------------------------------------- |
| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
| **Audit Log** | Administrative actions tracked in `audit_log` table |
| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
| **Günlük Saklama** | `CALL_LOG_RETENTION_DAYS` sonrasında otomatik temizleme |
| **Günlük Tutmama Tercihi** | API anahtarı başına `noLog` bayrağı istek kaydını devre dışı bırakır |
| **Denetim Günlüğü**| `audit_log` tablosunda izlenen yönetim eylemleri |
| **MCP Denetimi** | Tüm MCP araç çağrıları için SQLite tabanlı denetim kaydı |
| **Zod Doğrulaması**| Modül yükleme sırasında Zod v4 şemalarıyla doğrulanan tüm API girdileri |
---
## Required Environment Variables
## Gerekli Ortam Değişkenleri
All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
Sunucuyu başlatmadan önce tüm gizli anahtarlar ayarlanmalıdır. Eksik veya zayıf olmaları durumunda sunucu **hızlı bir şekilde hata vererek (fail fast)** durur.
```bash
# REQUIRED — server will not start without these:
JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
# GEREKLİ — sunucu bunlar olmadan başlamaz:
JWT_SECRET=$(openssl rand -base64 48) # min 32 karakter
API_KEY_SECRET=$(openssl rand -hex 32) # min 16 karakter
# RECOMMENDED — enables encryption at rest:
# ÖNERİLEN — dinlenmede şifrelemeyi etkinleştirir:
STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
```
The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
Sunucu `changeme`, `secret` veya `password` gibi bilinen zayıf değerleri açıkça reddeder.
---
## Docker Security
## Docker Güvenliği
- Use non-root user in production
- Mount secrets as read-only volumes
- Never copy `.env` files into Docker images
- Use `.dockerignore` to exclude sensitive files
- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
- Üretimde root olmayan bir kullanıcı kullanın
- Gizli anahtarları salt okunur birimler (read-only volumes) olarak bağlayın
- `.env` dosyalarını asla Docker imajlarına kopyalamayın
- Hassas dosyaları hariç tutmak için `.dockerignore` kullanın
- HTTPS arkasındayken `AUTH_COOKIE_SECURE=true` ayarlayın
```bash
docker run -d \
@@ -170,10 +195,52 @@ docker run -d \
---
## Dependencies
## Bağımlılıklar
- Run `npm audit` regularly
- Keep dependencies updated
- The project uses `husky` + `lint-staged` for pre-commit checks
- CI pipeline runs ESLint security rules on every push
- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
- Düzenli olarak `npm audit` çalıştırın (`npm run audit:deps` ana projeyi + electron'u kapsar)
- Bağımlılıkları güncel tutun
- Proje, commit öncesi kontroller için `husky` + `lint-staged` kullanır (lint-staged + check-docs-sync + check:any-budget:t11)
- CI hattı her push işleminde ESLint güvenlik kurallarını çalıştırır (`no-eval`, `no-implied-eval`, `no-new-func` = hata)
- Sağlayıcı sabitleri modül yükleme sırasında Zod aracılığıyla doğrulanır (`src/shared/validation/schemas.ts`)
- Varsayılan olarak güvenli kütüphaneler kullanılır: `dompurify` / `isomorphic-dompurify` (XSS), `jose` (JWT), `better-sqlite3` (parametreli sorgularla sıfır SQLi riski), `bcryptjs` (şifre karma)
## Katı Güvenlik Kuralları (Hard Security Rules)
Bu kurallar araçlar ve inceleyiciler tarafından zorunlu kılınmıştır:
1. **Sırları asla commit etmeyin**`.env` gitignore edilmiştir; `.env.example` şablondur (sabit değerler yok, yalnızca yorumlar — bkz. PUBLIC_CREDS.md)
2. **Asla `eval()`, `new Function()` veya dolaylı eval kullanmayın** — ESLint tarafından zorunlu kılınır
3. **Husky kancalarını asla atlamayın** (`--no-verify`, `--no-gpg-sign`), açık operatör onayı olmadan
4. **Rotalarda asla ham SQL yazmayın** — her zaman `src/lib/db/` üzerinden geçin (parametrelendirilmiş)
5. **Girdileri her zaman Zod ile doğrulayın**`src/shared/validation/schemas.ts`
6. **Yukarı akış başlıklarını her zaman temizleyin**`src/shared/constants/upstreamHeaders.ts` içindeki engelleme listesi
7. **Kimlik bilgilerini dinlenmede şifreleyin**`src/lib/db/encryption.ts` aracılığıyla AES-256-GCM
8. **Genel yukarı akış OAuth kimlikleri `resolvePublicCred()` aracılığıyla kullanılmalıdır** — kaynak koda asla `AIza…` / `GOCSPX-…` / `…apps.googleusercontent.com` sabit değerlerini gömmeyin. Bkz. [`docs/security/PUBLIC_CREDS.md`](docs/security/PUBLIC_CREDS.md).
9. **Hata yanıtları `buildErrorBody()` / `sanitizeErrorMessage()` üzerinden geçmelidir** — HTTP / SSE / executor / MCP yanıt gövdelerine asla ham `err.stack` / `err.message` koymayın. Bkz. [`docs/security/ERROR_SANITIZATION.md`](docs/security/ERROR_SANITIZATION.md).
10. **`exec()` / `spawn()` çalışma zamanı değerleri `env` seçeneği üzerinden iletilmelidir** — kabuk komutlarına harici yolları veya güvenilmeyen değerleri asla dize birleştirme ile eklemeyin. Referans: `src/mitm/cert/install.ts::updateNssDatabases`.
11. **Varsayılan olarak güvenli kütüphaneleri tercih edin** — bkz. [tldrsec/awesome-secure-defaults](https://github.com/tldrsec/awesome-secure-defaults) (Helmet.js, DOMPurify, ssrf-req-filter, safe-regex, Google Tink). Kendi çözümünüzü yazmadan önce bunlara başvurun.
## Tedarik Zinciri Tarayıcı Bulguları (Socket.dev / Snyk / Benzeri)
Yayımlanan `omniroute` npm paketi, Next.js `output: "standalone"` derlemesini paketler; bu da belgelenmiş ayrıcalıklı özellikler (MITM, Zed içe aktarma, Cloud Sync, gömülü servis süpervizörü) dahil her rota işleyicisinin `.next/server/*.js` küçültülmüş yığınlarında yer alması anlamına gelir. Sezgisel tedarik zinciri tarayıcıları bu yığınları sıklıkla kötü amaçlı yazılım imzalarıyla eşleştirebilir.
Her bulgu kategorisi için proje yöneticisi onay beyanı tutulmaktadır:
- **[`docs/security/SOCKET_DEV_FINDINGS.md`](docs/security/SOCKET_DEV_FINDINGS.md)** —
bulgu başına harita: kaynak dosya ↔ işaretlenen yığın ↔ davranış ↔ v3.8.6'da uygulanan hafifletme.
- İşaretlenen her fonksiyondaki kaynak içi `SECURITY-AUDITOR-NOTE:` blokları aynı belgeye işaret eder.
Geliştirme hattında uyarıları esnetemeyen kullanıcılar için: `OMNIROUTE_BUILD_PROFILE=minimal npm run build` ile derleme yapın. Bu, dört hassas modülü çalışma zamanında HTTP 503 `feature-disabled` döndüren taslaklarla değiştirir; böylece ayrıcalıklı kod yolları pakette fiziksel olarak bulunmaz. Yayımlama tarifi için bkz. [`docs/security/SOCKET_DEV_FINDINGS.md`](docs/security/SOCKET_DEV_FINDINGS.md).
## Referanslar
- [`docs/architecture/AUTHZ_GUIDE.md`](docs/architecture/AUTHZ_GUIDE.md) — yetkilendirme hattı
- [`docs/security/GUARDRAILS.md`](docs/security/GUARDRAILS.md) — güvenlik önlemleri çerçevesi
- [`docs/security/COMPLIANCE.md`](docs/security/COMPLIANCE.md) — denetim günlüğü ve saklama
- [`docs/security/PUBLIC_CREDS.md`](docs/security/PUBLIC_CREDS.md) — genel yukarı akış kimlik bilgileri için **zorunlu** model
- [`docs/security/ERROR_SANITIZATION.md`](docs/security/ERROR_SANITIZATION.md) — hata yanıtları için **zorunlu** model
- [`docs/security/SOCKET_DEV_FINDINGS.md`](docs/security/SOCKET_DEV_FINDINGS.md) — tedarik zinciri tarayıcı bulguları için onay beyanı
- [`docs/architecture/RESILIENCE_GUIDE.md`](docs/architecture/RESILIENCE_GUIDE.md) — devre kesici + soğuma süresi + model kilitleme
- [`docs/security/STEALTH_GUIDE.md`](docs/security/STEALTH_GUIDE.md) — TLS parmak izi (yasal/etik bildirim)
- [`CLAUDE.md`](CLAUDE.md) — yapay zeka ajanları için katı kurallar
- [tldrsec/awesome-secure-defaults](https://github.com/tldrsec/awesome-secure-defaults) — derlenmiş varsayılan olarak güvenli kütüphaneler

File diff suppressed because it is too large Load Diff

View File

@@ -1,587 +1,107 @@
# omniroute — Codebase Documentation (Türkçe)
---
title: "OmniRoute Kod Tabanı Dokümantasyonu"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇩 [bn](../../bn/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇷 [fa](../../fa/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [gu](../../gu/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [hi](../../hi/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [mr](../../mr/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇪 [sw](../../sw/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [ta](../../ta/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [te](../../te/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇷 [tr](../../tr/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇰 [ur](../../ur/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md)
# OmniRoute Kod Tabanı Dokümantasyonu (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇧🇩 [bn](../../bn/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇮🇷 [fa](../../fa/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [gu](../../gu/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [hi](../../hi/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [mr](../../mr/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../..//no/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇰🇪 [sw](../../sw/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [ta](../../ta/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [te](../../te/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇹🇷 [tr](../../tr/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇵🇰 [ur](../../ur/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/architecture/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/architecture/CODEBASE_DOCUMENTATION.md)
---
> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
> **Hedef Kitle:** OmniRoute'a katkıda bulunan veya üzerine entegrasyonlar oluşturan mühendisler.
>
> Yüksek düzey mimari diyagramları ve her alt sistemin gerekçeleri için [ARCHITECTURE.md](docs/architecture/ARCHITECTURE.md) dosyasını okuyun.
Bu belge, yeni bir mühendisin proje ağacında gezinebilmesi, çalışma zamanı katmanlarını anlaması ve yeni modüller icat etmeden nereye kod ekleyeceğini bilmesi için **bugün depoda neyin var olduğunu**ıklar.
---
## 1. What Is omniroute?
## 1. Teknoloji Yığını
omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
| Alan | Tercih |
| ------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Web framework | **Next.js 16** (App Router, standalone çıktı, global middleware yok) |
| Dil | **TypeScript 6.0+** — hedef `ES2022`, `module: esnext`, `moduleResolution: bundler`, `strict: false` |
| Çalışma Zamanı| **Node.js** `>=22.22.2 <23` veya `>=24.0.0 <27` |
| Veritabanı | `better-sqlite3` ile **SQLite** (singleton, WAL günlük kaydı) |
| Masaüstü | **Electron 41** + `electron-builder` (`electron/` altında ayrı çalışma alanı) |
| Testler | **Node yerel test çalıştırıcısı** (unit/integration), **Vitest** (MCP, autoCombo, önbellek), **Playwright** (E2E) |
| Derleme | `scripts/build/build-next-isolated.mjs` üzerinden Next.js standalone |
| Lint/Format | ESLint flat config + Prettier (`lint-staged` ile Husky pre-commit) |
| Modül Sistemi | Her yerde ESM (`"type": "module"`) |
| Çalışma Alanı | npm workspace — `open-sse` alt çalışma alanıdır |
> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
Yol Takma Adları (`tsconfig.json`):
Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
- `@/*``src/*`
- `@omniroute/open-sse``open-sse/index.ts`
- `@omniroute/open-sse/*``open-sse/*`
Varsayılan HTTP portu: **`20128`** (API ve pano aynı süreci paylaşır). Veri dizini `DATA_DIR` ortam değişkenidir (varsayılan: `~/.omniroute/`).
---
## 2. Architecture Overview
```mermaid
graph LR
subgraph Clients
A[Claude CLI]
B[Codex]
C[Cursor IDE]
D[OpenAI-compatible]
end
subgraph omniroute
E[Handler Layer]
F[Translator Layer]
G[Executor Layer]
H[Services Layer]
end
subgraph Providers
I[Anthropic Claude]
J[Google Gemini]
K[OpenAI / Codex]
L[GitHub Copilot]
M[AWS Kiro]
N[Antigravity]
O[Cursor API]
end
A --> E
B --> E
C --> E
D --> E
E --> F
F --> G
G --> I
G --> J
G --> K
G --> L
G --> M
G --> N
G --> O
H -.-> E
H -.-> G
```
### Core Principle: Hub-and-Spoke Translation
All format translation passes through **OpenAI format as the hub**:
## 2. Depo Düzeni
```
Client Format → [OpenAI Hub] → Provider Format (request)
Provider Format → [OpenAI Hub] → Client Format (response)
```
This means you only need **N translators** (one per format) instead of **N²** (every pair).
---
## 3. Project Structure
```
omniroute/
├── open-sse/ ← Core proxy library (portable, framework-agnostic)
│ ├── index.js ← Main entry point, exports everything
│ ├── config/ ← Configuration & constants
│ ├── executors/ ← Provider-specific request execution
│ ├── handlers/ ← Request handling orchestration
│ ├── services/ ← Business logic (auth, models, fallback, usage)
│ ├── translator/ ← Format translation engine
│ │ ├── request/ ← Request translators (8 files)
│ │ ├── response/ ← Response translators (7 files)
│ │ └── helpers/ ← Shared translation utilities (6 files)
│ └── utils/ ← Utility functions
├── src/ ← Application layer (Express/Worker runtime)
│ ├── app/ ← Web UI, API routes, middleware
│ ├── lib/ ← Database, auth, and shared library code
│ ├── mitm/ ← Man-in-the-middle proxy utilities
│ ├── models/ ← Database models
│ ├── shared/ ← Shared utilities (wrappers around open-sse)
│ ├── sse/ ← SSE endpoint handlers
│ └── store/ ← State management
├── data/ ← Runtime data (credentials, logs)
│ └── provider-credentials.json (external credentials override, gitignored)
└── tester/ ← Test utilities
OmniRoute/
├── src/ Next.js uygulaması (App Router, kütüphaneler, alan katmanı, sunucu, paylaşılanlar)
├── open-sse/ Akış motoru çalışma alanı (@omniroute/open-sse)
├── electron/ Masaüstü uygulaması (Electron 41 main + preload)
├── bin/ CLI giriş noktaları (omniroute, reset-password)
├── tests/ Birim, entegrasyon, e2e, protokol, çevirmen, güvenlik testleri
├── scripts/ Derleme, senkronizasyon, kontrol, migrasyon ve çalışma zamanı yardımcı betikleri
├── docs/ Genel dokümantasyon
├── public/ Statik varlıklar, PWA manifesti, servis çalışanı
├── config/ Çalışma zamanı yapılandırma örnekleri
├── CLAUDE.md Claude Code için kurallar
├── AGENTS.md Yapay zeka ajanları için derin mimari referansı
├── package.json Çalışma alanı kökü
└── tsconfig.json Yol takma adları ve derleyici seçenekleri
```
---
## 4. Module-by-Module Breakdown
## 3. `src/` — Next.js Uygulaması
### 4.1 Config (`open-sse/config/`)
The **single source of truth** for all provider configuration.
| File | Purpose |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
#### Credential Loading Flow
```mermaid
flowchart TD
A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
B --> C{"data/provider-credentials.json\nexists?"}
C -->|Yes| D["credentialLoader reads JSON"]
C -->|No| E["Use hardcoded defaults"]
D --> F{"For each provider in JSON"}
F --> G{"Provider exists\nin PROVIDERS?"}
G -->|No| H["Log warning, skip"]
G -->|Yes| I{"Value is object?"}
I -->|No| J["Log warning, skip"]
I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
K --> F
H --> F
J --> F
F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
E --> L
```
src/
├── app/ App Router sayfaları + API rotaları
├── lib/ Çekirdek kütüphaneler (DB, kimlik doğrulama, OAuth, yetenekler, bellek vb.)
├── domain/ Saf alan katmanı (politika, geri dönüş, maliyet, kilitleme vb.)
├── server/ Yalnızca sunucu tarafı modüller (authz, cors, auth)
├── shared/ Tipler, sabitler, doğrulama, sözleşmeler, yardımcılar
├── mitm/ CLI entegrasyonu için Man-in-the-middle proxy yardımcıları
├── models/ Yerel model meta verileri / takma adlar
├── sse/ src/ altında yaşayan SSE işleyicileri
├── store/ İstemci tarafı Zustand durum depoları
├── middleware/ Rota düzeyinde ara yazılım yardımcıları (Next.js global middleware DEĞİL)
└── types/ TypeScript tip tanımları
```
---
### 4.2 Executors (`open-sse/executors/`)
## 4. `open-sse/` — Akış ve Yürütücü Motoru
Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
```mermaid
classDiagram
class BaseExecutor {
+buildUrl(model, stream, options)
+buildHeaders(credentials, stream, body)
+transformRequest(body, model, stream, credentials)
+execute(url, options)
+shouldRetry(status, error)
+refreshCredentials(credentials, log)
}
class DefaultExecutor {
+refreshCredentials()
}
class AntigravityExecutor {
+buildUrl()
+buildHeaders()
+transformRequest()
+shouldRetry()
+refreshCredentials()
}
class CursorExecutor {
+buildUrl()
+buildHeaders()
+transformRequest()
+parseResponse()
+generateChecksum()
}
class KiroExecutor {
+buildUrl()
+buildHeaders()
+transformRequest()
+parseEventStream()
+refreshCredentials()
}
BaseExecutor <|-- DefaultExecutor
BaseExecutor <|-- AntigravityExecutor
BaseExecutor <|-- CursorExecutor
BaseExecutor <|-- KiroExecutor
BaseExecutor <|-- CodexExecutor
BaseExecutor <|-- GithubExecutor
```
| Executor | Provider | Key Specializations |
| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
---
### 4.3 Handlers (`open-sse/handlers/`)
The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
| File | Purpose |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
#### Request Lifecycle (chatCore.ts)
```mermaid
sequenceDiagram
participant Client
participant chatCore
participant Translator
participant Executor
participant Provider
Client->>chatCore: Request (any format)
chatCore->>chatCore: Detect source format
chatCore->>chatCore: Check bypass patterns
chatCore->>chatCore: Resolve model & provider
chatCore->>Translator: Translate request (source → OpenAI → target)
chatCore->>Executor: Get executor for provider
Executor->>Executor: Build URL, headers, transform request
Executor->>Executor: Refresh credentials if needed
Executor->>Provider: HTTP fetch (streaming or non-streaming)
alt Streaming
Provider-->>chatCore: SSE stream
chatCore->>chatCore: Pipe through SSE transform stream
Note over chatCore: Transform stream translates<br/>each chunk: target → OpenAI → source
chatCore-->>Client: Translated SSE stream
else Non-streaming
Provider-->>chatCore: JSON response
chatCore->>Translator: Translate response
chatCore-->>Client: Translated JSON
end
alt Error (401, 429, 500...)
chatCore->>Executor: Retry with credential refresh
chatCore->>chatCore: Account fallback logic
end
open-sse/
├── executors/ Sağlayıcıya özel istek yürütücüleri (101 modül)
├── handlers/ API türü başına istek işleyicileri (chat, responses, embeddings, images vb.)
├── mcp-server/ 110 araç ve 33 kapsam içeren yerleşik MCP sunucusu
├── services/ Yönlendirme, hız sınırlamaları, auto-combo, oturum yönetimi vb.
├── translator/ OpenAI ↔ Claude ↔ Gemini ↔ Ollama ↔ DeepSeek format çevirmenleri
├── transformer/ OpenAI Responses API dönüştürücüsü
└── utils/ Akış, TLS, proxy, günlük kaydı yardımcıları
```
---
### 4.4 Services (`open-sse/services/`)
## 5. `tests/` — Test Paketleri
Business logic that supports the handlers and executors.
| File | Purpose |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
| `model.ts` | Model string parsing (`claude/model-name``{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
#### Token Refresh Deduplication
```mermaid
sequenceDiagram
participant R1 as Request 1
participant R2 as Request 2
participant Cache as refreshPromiseCache
participant OAuth as OAuth Provider
R1->>Cache: getAccessToken("gemini", token)
Cache->>Cache: No in-flight promise
Cache->>OAuth: Start refresh
R2->>Cache: getAccessToken("gemini", token)
Cache->>Cache: Found in-flight promise
Cache-->>R2: Return existing promise
OAuth-->>Cache: New access token
Cache-->>R1: New access token
Cache-->>R2: Same access token (shared)
Cache->>Cache: Delete cache entry
```
#### Account Fallback State Machine
```mermaid
stateDiagram-v2
[*] --> Active
Active --> Error: Request fails (401/429/500)
Error --> Cooldown: Apply backoff
Cooldown --> Active: Cooldown expires
Active --> Active: Request succeeds (reset backoff)
state Error {
[*] --> ClassifyError
ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
ClassifyError --> NoFallback: 400 Bad Request
}
state Cooldown {
[*] --> ExponentialBackoff
ExponentialBackoff: Level 0 = 1s
ExponentialBackoff: Level 1 = 2s
ExponentialBackoff: Level 2 = 4s
ExponentialBackoff: Max = 2min
}
```
#### Combo Model Chain
```mermaid
flowchart LR
A["Request with\ncombo model"] --> B["Model A"]
B -->|"2xx Success"| C["Return response"]
B -->|"429/401/500"| D{"Fallback\neligible?"}
D -->|Yes| E["Model B"]
D -->|No| F["Return error"]
E -->|"2xx Success"| C
E -->|"429/401/500"| G{"Fallback\neligible?"}
G -->|Yes| H["Model C"]
G -->|No| F
H -->|"2xx Success"| C
H -->|"Fail"| I["All failed →\nReturn last status"]
```
---
### 4.5 Translator (`open-sse/translator/`)
The **format translation engine** using a self-registering plugin system.
#### Mimari
```mermaid
graph TD
subgraph "Request Translation"
A["Claude → OpenAI"]
B["Gemini → OpenAI"]
C["Antigravity → OpenAI"]
D["OpenAI Responses → OpenAI"]
E["OpenAI → Claude"]
F["OpenAI → Gemini"]
G["OpenAI → Kiro"]
H["OpenAI → Cursor"]
end
subgraph "Response Translation"
I["Claude → OpenAI"]
J["Gemini → OpenAI"]
K["Kiro → OpenAI"]
L["Cursor → OpenAI"]
M["OpenAI → Claude"]
N["OpenAI → Antigravity"]
O["OpenAI → Responses"]
end
```
| Directory | Files | Description |
| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
#### Key Design: Self-Registering Plugins
```javascript
// Each translator file calls register() on import:
import { register } from "../index.js";
register("claude", "openai", translateClaudeToOpenAI);
// The index.js imports all translator files, triggering registration:
import "./request/claude-to-openai.js"; // ← self-registers
```
---
### 4.6 Utils (`open-sse/utils/`)
| File | Purpose |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
| `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` | 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. |
#### SSE Streaming Pipeline
```mermaid
flowchart TD
A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
B --> C["Buffer lines\n(split on newline)"]
C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
D --> E{"Mode?"}
E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
F --> H["hasValuableContent()\nfilter empty chunks"]
G --> H
H -->|"Has content"| I["extractUsage()\ntrack token counts"]
H -->|"Empty"| J["Skip chunk"]
I --> K["formatSSE()\nserialize + clean perf_metrics"]
K --> L["TextEncoder\n(per-stream instance)"]
L --> M["Enqueue to\nclient stream"]
style A fill:#f9f,stroke:#333
style M fill:#9f9,stroke:#333
```
#### Request Logger Session Structure
```
logs/
└── claude_gemini_claude-sonnet_20260208_143045/
├── 1_req_client.json ← Raw client request
├── 2_req_source.json ← After initial conversion
├── 3_req_openai.json ← OpenAI intermediate format
├── 4_req_target.json ← Final target format
├── 5_res_provider.txt ← Provider SSE chunks (streaming)
├── 5_res_provider.json ← Provider response (non-streaming)
├── 6_res_openai.txt ← OpenAI intermediate chunks
├── 7_res_client.txt ← Client-facing SSE chunks
└── 6_error.json ← Error details (if any)
```
---
### 4.7 Application Layer (`src/`)
| Directory | Purpose |
| ------------- | ---------------------------------------------------------------------- |
| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
| `src/models/` | Database model definitions |
| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
| `src/store/` | Application state management |
#### Notable API Routes
| Route | Methods | Purpose |
| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
| `/api/sessions` | GET | Active session tracking and metrics |
| `/api/rate-limits` | GET | Per-account rate limit status |
---
## 5. Key Design Patterns
### 5.1 Hub-and-Spoke Translation
All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
### 5.2 Executor Strategy Pattern
Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
### 5.3 Self-Registering Plugin System
Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
### 5.4 Account Fallback with Exponential Backoff
When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
### 5.5 Combo Model Chains
A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
### 5.6 Stateful Streaming Translation
Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
### 5.7 Usage Safety Buffer
A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
---
## 6. Supported Formats
| Format | Direction | Identifier |
| ----------------------- | --------------- | ------------------ |
| OpenAI Chat Completions | source + target | `openai` |
| OpenAI Responses API | source + target | `openai-responses` |
| Anthropic Claude | source + target | `claude` |
| Google Gemini | source + target | `gemini` |
| Antigravity | source + target | `antigravity` |
| AWS Kiro | target only | `kiro` |
| Cursor | target only | `cursor` |
---
## 7. Supported Providers
| Provider | Auth Method | Executor | Key Notes |
| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
| OpenAI | API key | Default | Standard Bearer auth |
| Codex | OAuth | Codex | Injects system instructions, manages thinking |
| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
| Qwen | OAuth | Default | Standard auth |
| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
| OpenRouter | API key | Default | Standard Bearer auth |
| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
---
## 8. Data Flow Summary
### Streaming Request
```mermaid
flowchart LR
A["Client"] --> B["detectFormat()"]
B --> C["translateRequest()\nsource → OpenAI → target"]
C --> D["Executor\nbuildUrl + buildHeaders"]
D --> E["fetch(providerURL)"]
E --> F["createSSEStream()\nTRANSLATE mode"]
F --> G["parseSSELine()"]
G --> H["translateResponse()\ntarget → OpenAI → source"]
H --> I["extractUsage()\n+ addBuffer"]
I --> J["formatSSE()"]
J --> K["Client receives\ntranslated SSE"]
K --> L["logUsage()\nsaveRequestUsage()"]
```
### Non-Streaming Request
```mermaid
flowchart LR
A["Client"] --> B["detectFormat()"]
B --> C["translateRequest()\nsource → OpenAI → target"]
C --> D["Executor.execute()"]
D --> E["translateResponse()\ntarget → OpenAI → source"]
E --> F["Return JSON\nresponse"]
```
### Bypass Flow (Claude CLI)
```mermaid
flowchart LR
A["Claude CLI request"] --> B{"Match bypass\npattern?"}
B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
B -->|"No match"| D["Normal flow"]
C --> E["Translate to\nsource format"]
E --> F["Return without\ncalling provider"]
```
- `tests/unit/`: Node.js yerleşik test çalıştırıcısı ile 2.700'den fazla test dosyası
- `tests/integration/`: Modüller arası entegrasyon testleri
- `tests/e2e/`: Playwright uçtan uca tarayıcı testleri
- `tests/security/`: İstem enjeksiyonu, PII, yetkilendirme güvenlik testleri
- `tests/translator/`: Format çevirmen doğruluk testleri

View File

@@ -1,106 +1,103 @@
# Guia Completo: Cloudflare Tunnel & Zero Trust (Split-Port) (Türkçe)
# Kapsamlı Kılavuz: Cloudflare Tunnel ve Zero Trust (Split-Port) (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/cloudflare-zero-trust-guide.md) · 🇪🇸 [es](../../es/docs/cloudflare-zero-trust-guide.md) · 🇫🇷 [fr](../../fr/docs/cloudflare-zero-trust-guide.md) · 🇩🇪 [de](../../de/docs/cloudflare-zero-trust-guide.md) · 🇮🇹 [it](../../it/docs/cloudflare-zero-trust-guide.md) · 🇷🇺 [ru](../../ru/docs/cloudflare-zero-trust-guide.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/cloudflare-zero-trust-guide.md) · 🇯🇵 [ja](../../ja/docs/cloudflare-zero-trust-guide.md) · 🇰🇷 [ko](../../ko/docs/cloudflare-zero-trust-guide.md) · 🇸🇦 [ar](../../ar/docs/cloudflare-zero-trust-guide.md) · 🇮🇳 [hi](../../hi/docs/cloudflare-zero-trust-guide.md) · 🇮🇳 [in](../../in/docs/cloudflare-zero-trust-guide.md) · 🇹🇭 [th](../../th/docs/cloudflare-zero-trust-guide.md) · 🇻🇳 [vi](../../vi/docs/cloudflare-zero-trust-guide.md) · 🇮🇩 [id](../../id/docs/cloudflare-zero-trust-guide.md) · 🇲🇾 [ms](../../ms/docs/cloudflare-zero-trust-guide.md) · 🇳🇱 [nl](../../nl/docs/cloudflare-zero-trust-guide.md) · 🇵🇱 [pl](../../pl/docs/cloudflare-zero-trust-guide.md) · 🇸🇪 [sv](../../sv/docs/cloudflare-zero-trust-guide.md) · 🇳🇴 [no](../../no/docs/cloudflare-zero-trust-guide.md) · 🇩🇰 [da](../../da/docs/cloudflare-zero-trust-guide.md) · 🇫🇮 [fi](../../fi/docs/cloudflare-zero-trust-guide.md) · 🇵🇹 [pt](../../pt/docs/cloudflare-zero-trust-guide.md) · 🇷🇴 [ro](../../ro/docs/cloudflare-zero-trust-guide.md) · 🇭🇺 [hu](../../hu/docs/cloudflare-zero-trust-guide.md) · 🇧🇬 [bg](../../bg/docs/cloudflare-zero-trust-guide.md) · 🇸🇰 [sk](../../sk/docs/cloudflare-zero-trust-guide.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/cloudflare-zero-trust-guide.md) · 🇮🇱 [he](../../he/docs/cloudflare-zero-trust-guide.md) · 🇵🇭 [phi](../../phi/docs/cloudflare-zero-trust-guide.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/cloudflare-zero-trust-guide.md) · 🇨🇿 [cs](../../cs/docs/cloudflare-zero-trust-guide.md) · 🇹🇷 [tr](../../tr/docs/cloudflare-zero-trust-guide.md)
---
Este guia documenta o padrão ouro de infraestrutura de rede para proteger o **OmniRoute** e expor sua aplicação de forma segura para a internet, **sem abrir nenhuma porta (Zero Inbound)**.
Bu kılavuz, **OmniRoute**'u korumak ve uygulamanızı **hiçbir gelen bağlantı portu açmadan (Zero Inbound)** internete güvenli bir şekilde sunmak için altın standart ağ altyapısını belgeler.
## O que foi feito na sua VM?
## Sanal Makinenizde (VM) Ne Yapıldı?
Nós ativamos o OmniRoute em modo **Split-Port** através do PM2:
OmniRoute'u PM2 aracılığıyla **Split-Port (Ayrık Port)** modunda etkinleştiriyoruz:
- **Porta \`20128\`:** Roda **apenas a API** `/v1`.
- **Porta \`20129\`:** Roda **apenas o Dashboard** Administrativo visual.
- **Port `20128`:** **Yalnızca API** (`/v1`) çalıştırır.
- **Port `20129`:** **Yalnızca görsel Yönetim Panosunu** çalıştırır.
Além disso, o serviço interno exige \`REQUIRE_API_KEY=true\`, o que significa que nenhum agente pode consumir os endpoints da API sem enviar um "Bearer Token" legítimo gerado na aba API Keys do Painel.
Ayrıca dahili servis `REQUIRE_API_KEY=true` gerektirir; bu da hiçbir ajanın Panonun API Keys sekmesinde oluşturulan geçerli bir "Bearer Token" göndermeden API uç noktalarını tüketemeyeceği anlamına gelir.
Isso nos permite criar duas regras completamente independentes na rede. É aqui que entra o **Cloudflare Tunnel (cloudflared)**.
Bu yapı ağda tamamen bağımsız iki kural oluşturmamıza olanak tanır. **Cloudflare Tunnel (cloudflared)** burada devreye girer.
---
## 1. Como Criar o Túnel na Cloudflare
## 1. Cloudflare'de Tünel Oluşturma
O utilitário \`cloudflared\` já está instalado na sua máquina. Siga os passos na nuvem:
`cloudflared` yardımcı programı makinenizde kuruludur. Bulut adımlarını izleyin:
1. Acesse seu painel **Cloudflare Zero Trust** (One.dash.cloudflare.com).
2. No menu à esquerda, vá em **Networks > Tunnels**.
3. Clique em **Add a Tunnel**, escolha **Cloudflared** e dê o nome \`OmniRoute-VM\`.
4. Ele vai gerar um comando na tela chamado "Install and run a connector". **Você só precisa copiar o Token (a string longa após `--token`)**.
5. Logue via SSH na sua máquina virtual (ou Terminal do Proxmox) e execute:
\`\`\`bash
# Inicia e amarra o túnel permanentemente à sua conta
cloudflared service install SEU_TOKEN_GIGANTE_AQUI
\`\`\`
1. **Cloudflare Zero Trust** panonuza erişin (one.dash.cloudflare.com).
2. Sol menüden **Networks > Tunnels** yolunu izleyin.
3. **Add a Tunnel** seçeneğine tıklayın, **Cloudflared** seçin ve tünele `OmniRoute-VM` adını verin.
4. Ekranda "Install and run a connector" başlıklı bir komut oluşturulacaktır. **Yalnızca Belirteci (`--token` sonrasındaki uzun dize) kopyalamanız yeterlidir**.
5. Sanal makinenize SSH ile bağlanın ve çalıştırın:
```bash
# Tüneli başlatır ve kalıcı olarak hesabınıza bağlar
cloudflared service install BURAYA_UZUN_TOKENINIZI_YAPISTIRIN
```
---
## 2. Configurando o Roteamento (Public Hostnames)
## 2. Yönlendirmeyi Yapılandırma (Public Hostnames)
Ainda na tela do Tunnel recém-criado, vá para a aba **Public Hostnames** e adicione as **duas** rotas, aproveitando a separação que fizemos:
Yeni oluşturulan Tunnel ekranında **Public Hostnames** sekmesine gidin ve yaptığımız ayrımdan yararlanarak **iki** rotayı ekleyin:
### Rota 1: API Segura (Limitada)
### Rota 1: Güvenli API (Kısıtlı)
- **Subdomain:** \`api\`
- **Domain:** \`seuglobal.com.br\` (escolha seu domínio real)
- **Service Type:** \`HTTP\`
- **URL:** \`127.0.0.1:20128\` _(Porta interna da API)_
- **Subdomain:** `api`
- **Domain:** `alanadiniz.com` (kendi gerçek alan adınızı seçin)
- **Service Type:** `HTTP`
- **URL:** `127.0.0.1:20128` _(Dahili API portu)_
### Rota 2: Painel Zero Trust (Fechado)
### Rota 2: Zero Trust Pano (Kapalı)
- **Subdomain:** \`omniroute\` ou \`painel\`
- **Domain:** \`seuglobal.com.br\`
- **Service Type:** \`HTTP\`
- **URL:** \`127.0.0.1:20129\` _(Porta interna do App/Visual)_
Neste momento, a conectividade "Física" está resolvida. Agora vamos blindar de verdade.
- **Subdomain:** `omniroute` veya `panel`
- **Domain:** `alanadiniz.com`
- **Service Type:** `HTTP`
- **URL:** `127.0.0.1:20129` _(Dahili Uygulama/Pano portu)_
---
## 3. Blindando o Painel com Zero Trust (Access)
## 3. Panoyu Zero Trust (Access) ile Güçlendirme
Nenhuma senha local protege melhor o seu painel do que remover totalmente o acesso a ele da internet aberta.
Hiçbir yerel şifre, panonuzu internete tamamen kapatmaktan daha iyi koruyamaz.
1. No painel Zero Trust, vá em **Access > Applications > Add an application**.
2. Selecione **Self-hosted**.
3. Em **Application name**, coloque \`Painel OmniRoute\`.
4. Em **Application domain**, coloque \`omniroute.seuglobal.com.br\` (O mesmo que você fez na "Rota 2").
5. Clique em **Next**.
6. Em **Rule action**, escolha \`Allow\`. Em nome da Rule coloque \`Admin Apenas\`.
7. Em **Include**, no seletor de "Selector" escolha \`Emails\` e digite o seu email, por exemplo \`admin@spgeo.com.br\`.
8. Salve (`Add application`).
1. Zero Trust panosunda **Access > Applications > Add an application** seçeneğine gidin.
2. **Self-hosted** seçin.
3. **Application name** kısmına `OmniRoute Paneli` yazın.
4. **Application domain** kısmına `omniroute.alanadiniz.com` ("Rota 2"de belirlediğiniz adres) yazın.
5. **Next** butonuna tıklayın.
6. **Rule action** için `Allow` seçin. Kural adına `Yalnızca Yönetici` yazın.
7. **Include** altında "Selector" olarak `Emails` seçin ve e-posta adresinizi girin (örn. `admin@alanadiniz.com`).
8. Kaydedin (`Add application`).
> **O que isso fez:** Se você tentar abrir \`omniroute.seuglobal.com.br\`, não cai mais na sua aplicação OmniRoute! Cai numa tela elegante da Cloudflare pedindo para digitar seu email. Somente se você (ou o email que você botou) for digitado lá, ele recebe no Outlook/Gmail um código de 6 dígitos temporário que libera o túnel até a porta \`20129\`.
> **Bu ne sağladı:** Artık `omniroute.alanadiniz.com` adresini açtığınızda doğrudan uygulamanıza düşmez! Cloudflare'in e-posta isteyen şık bir giriş ekranı çıkar. Yalnızca belirttiğiniz e-posta girildiğinde, gelen kutunuza `20129` portuna tüneli açan tek kullanımlık 6 haneli bir kod gönderilir.
---
## 4. Limitando e Protegendo a API com Rate Limit (WAF)
## 4. API'yi Hız Sınırı (WAF) ile Korumak
O Dashboard do Zero Trust não se aplica à rota da API (\`api.seuglobal.com.br\`), porque é um acesso programático via ferramentas automatizadas (agentes) sem navegador. Para ele, usaremos o Firewall principal (WAF) da Cloudflare.
Zero Trust Panosu API rotasına (`api.alanadiniz.com`) uygulanmaz; çünkü bu tarayıcısız, otomatik araçlar (ajanlar) aracılığıyla yapılan programatik bir erişimdir. Bunun için Cloudflare'in ana Güvenlik Duvarını (WAF) kullanacağız.
1. Acesse o **Painel Normal** da Cloudflare (dash.cloudflare.com) e entre no seu Domínio.
2. No menu esquerdo, vá em **Security > WAF > Rate limiting rules**.
3. Clique em **Create rule**.
4. **Name:** \`Anti-Abuso OmniRoute API\`
1. Cloudflare **Normal Panosuna** (dash.cloudflare.com) erişin ve Alan Adınıza girin.
2. Sol menüden **Security > WAF > Rate limiting rules** yolunu izleyin.
3. **Create rule** butonuna tıklayın.
4. **Name:** `OmniRoute API Kötüye Kullanım Önleme`
5. **If incoming requests match...**
- Escolha em Field: \`Hostname\`
- Operator: \`equals\`
- Value: \`api.seuglobal.com.br\`
6. Em **With the same characteristics:** Mantenha \`IP\`.
7. Nos limites (Limit):
- **When requests exceed:** \`50\`
- **Period:** \`1 minute\`
8. No final, em **Action**: \`Block\` (Bloquear) e decida se o bloqueio dura por 1 minuto ou 1 hora.
- Field: `Hostname`
- Operator: `equals`
- Value: `api.alanadiniz.com`
6. **With the same characteristics:** `IP` olarak bırakın.
7. Sınırlar (Limit):
- **When requests exceed:** `50`
- **Period:** `1 minute`
8. **Action:** `Block` seçin ve engelleme süresini belirleyin (1 dakika veya 1 saat).
9. **Deploy**.
> **O que isso fez:** Ninguém pode mandar mais de 50 requisições num período de 60 segundos na sua URL de API. Como você roda vários agentes e os consumos por trás já batem rate limit e já rastreiam tokens, isso é apenas uma medida na Borda da Internet (Edge Layer) que protege sua Instância On-Premises de cair por estresse térmico antes mesmo do tráfego descer pelo túnel.
> **Bu ne sağladı:** Hiç kimse API URL'nize 60 saniyelik bir süre içinde 50'den fazla istek gönderemez. Bu, trafiğin tünelden sunucunuza inmesine gerek kalmadan ağın kenarında (Edge Layer) sunucunuzu aşırı yükten korur.
---
## Finalização
## Özet
1. A sua VM **não possui nenhuma porta exposta** em `/etc/ufw`.
2. O OmniRoute só conversa HTTPS saindo (\`cloudflared\`) e não recebendo TCP direto do mundo.
3. Seus requets pro OpenAI são ofuscados porque configuramos eles globalmente pra passar em um Proxy SOCKS5 (A nuvem não liga pro SOCKS5 porque ela vem Inbound).
4. Seu painel web tem 2-Factor com Email.
5. Sua API está ratelimitada na borda pela Cloudflare e só trafega Bearer Tokens.
1. Sanal makinenizde güvenlik duvarında (`/etc/ufw`) **hiçbir açık gelen port bulunmaz**.
2. OmniRoute yalnızca giden HTTPS (`cloudflared`) trafiğiyle haberleşir ve dünyadan doğrudan TCP bağlantısı almaz.
3. Yönetim web panonuz e-posta tabanlı İki Faktörlü Doğrulama (2FA) ile korunur.
4. API'niz Cloudflare tarafından sınırlandırılmıştır ve yalnızca Bearer Token'lar kabul edilir.

View File

@@ -4,62 +4,54 @@
---
`context-relay` is a combo strategy that keeps session continuity when the active account
rotates before the conversation is finished.
`context-relay`, konuşma tamamlanmadan önce aktif hesap değiştiğinde (rotasyon) oturum sürekliliğini koruyan bir kombo stratejisidir.
The current runtime behaves like priority routing for model selection, then adds a
handoff layer on top:
Mevcut çalışma zamanı model seçimi için öncelikli (priority) yönlendirme gibi davranır, ardından üzerine bir devir (handoff) katmanı ekler:
- before the active account is exhausted, OmniRoute generates a compact structured summary
- after authentication selects a different account for the same session, OmniRoute injects
that summary as a system message into the next request
- once the handoff is consumed successfully, it is removed from storage
- Aktif hesap tükenmeden önce OmniRoute kompakt ve yapılandırılmış bir özet üretir
- Kimlik doğrulama aynı oturum için farklı bir hesap seçtikten sonra, OmniRoute bu özeti sonraki isteğe bir sistem mesajı olarak enjekte eder
- Devir başarıyla tüketildiğinde depodan silinir
## When To Use It
## Ne Zaman Kullanılmalı
Use `context-relay` when all of the following are true:
Aşağıdakilerin tümü doğru olduğunda `context-relay` kullanın:
- the combo is expected to rotate between multiple accounts of the same provider
- losing short-term conversational continuity would hurt task quality
- the provider exposes enough quota information to predict an approaching account limit
- Kombonun aynı sağlayıcının birden çok hesabı arasında geçiş yapması bekleniyorsa
- Kısa vadeli konuşma sürekliliğini kaybetmek görev kalitesine zarar verecekse
- Sağlayıcı yaklaşan bir hesap sınırını tahmin etmek için yeterli kota bilgisi sunuyorsa
This is most useful for long-running coding or research sessions that may outlive a single
account window.
Bu özellik, tek bir hesap penceresinden daha uzun sürebilecek uzun kodlama veya araştırma oturumları için son derece kullanışlıdır.
## Runtime Flow
## Çalışma Zamanı Akışı
The current behavior is intentionally split across two runtime layers.
Mevcut davranış kasıtlı olarak iki çalışma zamanı katmanına ayrılmıştır.
### 0% to 84% quota used
### %0 ila %84 Kota Kullanımı
No handoff is generated. Requests behave like normal priority routing.
Hiçbir devir özeti üretilmez. İstekler normal öncelik yönlendirmesi gibi davranır.
### 85% to 94% quota used
### %85 ila %94 Kota Kullanımı
If the active provider is enabled in `handoffProviders`, OmniRoute generates a structured
handoff summary in the background before the account is fully exhausted.
Aktif sağlayıcı `handoffProviders` içinde etkinleştirilmişse, OmniRoute hesap tamamen tükenmeden önce arka planda yapılandırılmış bir devir özeti üretir.
Important details:
Önemli detaylar:
- the default warning threshold is `0.85`
- the hard stop for generation is `0.95`
- only one in-flight handoff generation is allowed per `sessionId + comboName`
- if an active handoff already exists for that session/combo, no duplicate summary is generated
- Varsayılan uyarı eşiği `0.85`'tir
- Üretim için kesin durma noktası `0.95`'tir
- `sessionId + comboName` başına yalnızca bir devam eden devir üretimine izin verilir
- Bu oturum/kombo için zaten etkin bir devir varsa, mükerrer özet üretilmez
### 95% or more quota used
### %95 veya Daha Fazla Kota Kullanımı
No new handoff is generated. At this point the system is already in or near exhaustion and
the runtime avoids scheduling another summary request.
Yeni bir devir üretilmez. Bu noktada sistem zaten tükenme sınırındadır veya tükenmiştir; çalışma zamanı başka bir özet isteği zamanlamaktan kaçınır.
### After account rotation
### Hesap Rotasyonundan Sonra
When the next request for the same session resolves to a different authenticated account,
OmniRoute prepends the stored handoff as a system message. Injection happens only after the
real account switch is known.
Aynı oturum için bir sonraki istek farklı bir kimliği doğrulanmış hesaba çözümlendiğinde, OmniRoute saklanan devir özetini bir sistem mesajı olarak başa ekler. Enjeksiyon yalnızca gerçek hesap değişikliği bilindikten sonra gerçekleşir.
## Handoff Payload
## Devir Yükü (Handoff Payload)
The persisted handoff payload is stored in `context_handoffs` and includes:
Kalıcı devir yükü `context_handoffs` tablosunda saklanır ve şunları içerir:
- `sessionId`
- `comboName`
@@ -74,57 +66,49 @@ The persisted handoff payload is stored in `context_handoffs` and includes:
- `generatedAt`
- `expiresAt`
The summary model is instructed to return a JSON object with this structure:
Özet modeline şu yapıda bir JSON nesnesi döndürmesi talimatı verilir:
```json
{
"summary": "Dense summary of what matters for continuity",
"keyDecisions": ["Decision 1", "Decision 2"],
"taskProgress": "What is done, what is pending, and the next step",
"activeEntities": ["fileA.ts", "feature X", "provider Y"]
"summary": "Süreklilik için önemli olan konuların yoğun özeti",
"keyDecisions": ["Karar 1", "Karar 2"],
"taskProgress": "Ne yapıldı, ne bekliyor ve bir sonraki adım",
"activeEntities": ["dosyaA.ts", "özellik X", "sağlayıcı Y"]
}
```
At injection time, OmniRoute converts that payload into a `<context_handoff>` system
message so the next account can continue with the correct local context.
Enjeksiyon anında OmniRoute bu yükü bir `<context_handoff>` sistem mesajına dönüştürür; böylece sonraki hesap doğru yerel bağlamla devam edebilir.
## Yapılandırma
`context-relay` supports these config fields:
`context-relay` şu yapılandırma alanlarını destekler:
- `handoffThreshold`: warning threshold for summary generation, default `0.85`
- `handoffModel`: optional model override used only for summary generation
- `handoffProviders`: allowlist of providers allowed to trigger handoff generation
- `handoffThreshold`: Özet üretimi için uyarı eşiği, varsayılan `0.85`
- `handoffModel`: Yalnızca özet üretimi için kullanılan isteğe bağlı model geçersiz kılma
- `handoffProviders`: Devir üretimini tetiklemesine izin verilen sağlayıcıların izin listesi
Global defaults can be configured in Settings, and combo-specific values can override them
in the Combos page.
Genel varsayılanlar Ayarlar sayfasında yapılandırılabilir ve kombo bazlı değerler bunları Kombolar sayfasında geçersiz kılabilir.
## Architectural Note
## Mimari Not
The current implementation does not use a standalone `handleContextRelayCombo` handler.
Mevcut uygulama bağımsız bir `handleContextRelayCombo` işleyicisi kullanmaz.
Instead:
Bunun yerine:
- `open-sse/services/combo.ts` decides whether a successful turn should generate a handoff
- `src/sse/handlers/chat.ts` injects the handoff only after authentication resolves the
actual account used for the request
- `open-sse/services/combo.ts` başarılı bir turun devir üretip üretmeyeceğine karar verir
- `src/sse/handlers/chat.ts` devir özetini yalnızca kimlik doğrulama istek için kullanılan gerçek hesabı belirledikten sonra enjekte eder
This split is intentional in the current codebase because the combo loop alone does not know
whether the request stayed on the same account or actually switched accounts.
## Sınırlamalar
## Limitations
- Etkili çalışma zamanı desteği şu anda `codex` kota rotasyonu üzerinde yoğunlaşmıştır.
- `handoffProviders` bir yapılandırma yüzeyi olarak modellenmiştir ancak gerçek devir üretimi hala sağlayıcıya özel kota altyapısına bağlıdır.
- Özet kasıtlı olarak kompakt ve yakın geçmişe dayalıdır; tam bir konuşma geçmişi tekrar oynatma mekanizması değildir.
- Devirler `sessionId + comboName` ile kapsama alınır ve otomatik olarak sona erer.
- Oturum hesap değiştirmezse, saklanan devir enjekte edilmez.
- Effective runtime support is currently centered on `codex` quota rotation.
- `handoffProviders` is already modeled as a config surface, but real handoff generation
still depends on provider-specific quota plumbing.
- The summary is intentionally compact and recent-history based; it is not a full transcript
replay mechanism.
- Handoffs are scoped by `sessionId + comboName` and expire automatically.
- If the session does not switch accounts, the stored handoff is not injected.
## Önerilen Kullanım Modeli
## Recommended Usage Pattern
- use multiple accounts from the same provider
- keep stable `sessionId` values across the session
- set `handoffThreshold` early enough to leave room for the background summary request
- treat the feature as continuity assistance, not as a replacement for persistent memory
- Aynı sağlayıcıdan birden fazla hesap kullanın
- Oturum boyunca kararlı `sessionId` değerleri koruyun
- Arka plan özet isteğine yer bırakmak için `handoffThreshold` değerini yeterince erken bir seviyeye ayarlayın
- Bu özelliği kalıcı belleğin yerine geçen bir mekanizma olarak değil, bir süreklilik desteği olarak değerlendirin

View File

@@ -1,38 +1,55 @@
# OmniRoute A2A Server Documentation (Türkçe)
---
title: "OmniRoute A2A Sunucu Dokümantasyonu"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇧🇩 [bn](../../bn/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇮🇷 [fa](../../fa/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇮🇳 [gu](../../gu/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇮🇳 [hi](../../hi/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇮🇳 [mr](../../mr/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇰🇪 [sw](../../sw/docs/A2A-SERVER.md) · 🇮🇳 [ta](../../ta/docs/A2A-SERVER.md) · 🇮🇳 [te](../../te/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇹🇷 [tr](../../tr/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇵🇰 [ur](../../ur/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md)
# OmniRoute A2A Sunucu Dokümantasyonu (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/frameworks/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/frameworks/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/frameworks/A2A-SERVER.md) · 🇧🇩 [bn](../../bn/docs/frameworks/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/frameworks/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/frameworks/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/frameworks/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/frameworks/A2A-SERVER.md) · 🇮🇷 [fa](../../fa/docs/frameworks/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/frameworks/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/frameworks/A2A-SERVER.md) · 🇮🇳 [gu](../../gu/docs/frameworks/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/frameworks/A2A-SERVER.md) · 🇮🇳 [hi](../../hi/docs/frameworks/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/frameworks/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/frameworks/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/frameworks/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/frameworks/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/frameworks/A2A-SERVER.md) · 🇮🇳 [mr](../../mr/docs/frameworks/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/frameworks/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/frameworks/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/frameworks/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/frameworks/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/frameworks/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/frameworks/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/frameworks/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/frameworks/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/frameworks/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/frameworks/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/frameworks/A2A-SERVER.md) · 🇰🇪 [sw](../../sw/docs/frameworks/A2A-SERVER.md) · 🇮🇳 [ta](../../ta/docs/frameworks/A2A-SERVER.md) · 🇮🇳 [te](../../te/docs/frameworks/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/frameworks/A2A-SERVER.md) · 🇹🇷 [tr](../../tr/docs/frameworks/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/frameworks/A2A-SERVER.md) · 🇵🇰 [ur](../../ur/docs/frameworks/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/frameworks/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/frameworks/A2A-SERVER.md)
---
> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
> Agent-to-Agent Protokolü v0.3 — Akıllı bir yönlendirme ajanı olarak OmniRoute
## Agent Discovery
A2A yüzeyinin iki arayüzü vardır:
- `POST /a2a` adresinde **JSON-RPC 2.0** (kurallı giriş noktası, `src/app/a2a/route.ts` içinde tanımlı).
- Panolar ve araçlar için `/api/a2a/*` altında **REST** (durum, görev listesi, iptal).
Görevler `A2ATaskManager` (`src/lib/a2a/taskManager.ts`, varsayılan 5 dakikalık TTL) tarafından izlenir. Yetenekler `src/lib/a2a/taskExecution.ts` içindeki `A2A_SKILL_HANDLERS` aracılığıyla dağıtılır.
## Ajan Keşfi (Agent Discovery)
```bash
curl http://localhost:20128/.well-known/agent.json
```
Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
OmniRoute'un yeteneklerini, becerilerini ve kimlik doğrulama gereksinimlerini açıklayan Ajan Kartını (Agent Card) döndürür.
---
## Authentication
## Kimlik Doğrulama
All `/a2a` requests require an API key via the `Authorization` header:
Tüm `/a2a` istekleri `Authorization` başlığı aracılığıyla bir API anahtarı gerektirir:
```
Authorization: Bearer YOUR_OMNIROUTE_API_KEY
Authorization: Bearer SIZIN_OMNIROUTE_API_ANAHTARINIZ
```
If no API key is configured on the server, authentication is bypassed.
Sunucuda hiçbir API anahtarı yapılandırılmamışsa, kimlik doğrulama atlanır.
## Etkinleştirme
A2A, **Uç Noktalar → A2A** anahtarıyla kontrol edilir ve varsayılan olarak devre dışıdır. Devre dışıyken, `GET /api/a2a/status` `status: "disabled"` ve `online: false` bildirir; `POST /a2a` çağrıları `-32000` JSON-RPC hata koduyla HTTP 503 döndürür.
---
## JSON-RPC 2.0 Methods
## JSON-RPC 2.0 Metotları
### `message/send` — Synchronous Execution
### `message/send` — Eşzamanlı Yürütme
Sends a message to a skill and waits for the complete response.
Bir yeteneğe mesaj gönderir ve tam yanıtı bekler.
```bash
curl -X POST http://localhost:20128/a2a \
@@ -50,151 +67,25 @@ curl -X POST http://localhost:20128/a2a \
}'
```
**Response:**
### `message/stream` — SSE Akışı
```json
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"task": { "id": "uuid", "state": "completed" },
"artifacts": [{ "type": "text", "content": "..." }],
"metadata": {
"routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
"cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
"resilience_trace": [
{ "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
],
"policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
}
}
}
```
`message/send` ile aynıdır ancak gerçek zamanlı akış için Server-Sent Events döndürür.
### `message/stream` — SSE Streaming
### `tasks/get` — Görev Durumu Alma
Same as `message/send` but returns Server-Sent Events for real-time streaming.
`params.id` ile bir görevin durumunu, yapıtlarını ve yürütme meta verilerini sorgular.
```bash
curl -N -X POST http://localhost:20128/a2a \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_KEY" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "message/stream",
"params": {
"skill": "smart-routing",
"messages": [{"role": "user", "content": "Explain quantum computing"}]
}
}'
```
### `tasks/cancel` — Görevi İptal Etme
**SSE Events:**
```
data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
: heartbeat 2026-03-03T17:00:00Z
data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
```
### `tasks/get` — Query Task Status
```bash
curl -X POST http://localhost:20128/a2a \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_KEY" \
-d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
```
### `tasks/cancel` — Cancel a Task
```bash
curl -X POST http://localhost:20128/a2a \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_KEY" \
-d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
```
Çalışan bir görevi iptal eder.
---
## Available Skills
## Desteklenen A2A Yetenekleri (Skills)
| Skill | Description |
| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
---
## Task Lifecycle
```
submitted → working → completed
→ failed
→ cancelled
```
- Tasks expire after 5 minutes (configurable)
- Terminal states: `completed`, `failed`, `cancelled`
- Event log tracks every state transition
---
## Error Codes
| Code | Meaning |
| :----- | :----------------------------- |
| -32700 | Parse error (invalid JSON) |
| -32600 | Invalid request / Unauthorized |
| -32601 | Method or skill not found |
| -32602 | Invalid params |
| -32603 | Internal error |
---
## Integration Examples
### Python (requests)
```python
import requests
resp = requests.post("http://localhost:20128/a2a", json={
"jsonrpc": "2.0", "id": "1",
"method": "message/send",
"params": {
"skill": "smart-routing",
"messages": [{"role": "user", "content": "Hello"}]
}
}, headers={"Authorization": "Bearer YOUR_KEY"})
result = resp.json()["result"]
print(result["artifacts"][0]["content"])
print(result["metadata"]["routing_explanation"])
```
### TypeScript (fetch)
```typescript
const resp = await fetch("http://localhost:20128/a2a", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer YOUR_KEY",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "message/send",
params: {
skill: "smart-routing",
messages: [{ role: "user", content: "Hello" }],
},
}),
});
const { result } = await resp.json();
console.log(result.metadata.routing_explanation);
```
1. **`smart-routing`** — Akıllı yönlendirme ve çok sağlayıcılı geri dönüş ile mesaj gönderme.
2. **`quota-management`** — Tüm bağlı sağlayıcılardaki kota durumunu ve sıfırlanma sürelerini kontrol etme.
3. **`provider-discovery`** — Uygun sağlayıcıları ve modelleri yeteneklere göre listeleme.
4. **`cost-analysis`** — Oturum veya zaman dilimi bazında maliyet analiz raporu alma.
5. **`health-report`** — Sistem çalışma süresi, devre kesiciler ve sağlayıcı sağlık durumu.
6. **`list-capabilities`** — Desteklenen tüm modelleri, komboları ve stratejileri listeleme.

View File

@@ -1,87 +1,102 @@
# OmniRoute MCP Server Documentation (Türkçe)
---
title: "OmniRoute MCP Sunucu Dokümantasyonu"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇧🇩 [bn](../../bn/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇮🇷 [fa](../../fa/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇮🇳 [gu](../../gu/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇮🇳 [hi](../../hi/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇮🇳 [mr](../../mr/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇰🇪 [sw](../../sw/docs/MCP-SERVER.md) · 🇮🇳 [ta](../../ta/docs/MCP-SERVER.md) · 🇮🇳 [te](../../te/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇹🇷 [tr](../../tr/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇵🇰 [ur](../../ur/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md)
# OmniRoute MCP Sunucu Dokümantasyonu (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/frameworks/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/frameworks/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/frameworks/MCP-SERVER.md) · 🇧🇩 [bn](../../bn/docs/frameworks/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/frameworks/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/frameworks/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/frameworks/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/frameworks/MCP-SERVER.md) · 🇮🇷 [fa](../../fa/docs/frameworks/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/frameworks/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/frameworks/MCP-SERVER.md) · 🇮🇳 [gu](../../gu/docs/frameworks/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/frameworks/MCP-SERVER.md) · 🇮🇳 [hi](../../hi/docs/frameworks/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/frameworks/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/frameworks/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/frameworks/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/frameworks/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/frameworks/MCP-SERVER.md) · 🇮🇳 [mr](../../mr/docs/frameworks/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/frameworks/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/frameworks/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/frameworks/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/frameworks/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/frameworks/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/frameworks/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/frameworks/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/frameworks/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/frameworks/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/frameworks/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/frameworks/MCP-SERVER.md) · 🇰🇪 [sw](../../sw/docs/frameworks/MCP-SERVER.md) · 🇮🇳 [ta](../../ta/docs/frameworks/MCP-SERVER.md) · 🇮🇳 [te](../../te/docs/frameworks/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/frameworks/MCP-SERVER.md) · 🇹🇷 [tr](../../tr/docs/frameworks/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/frameworks/MCP-SERVER.md) · 🇵🇰 [ur](../../ur/docs/frameworks/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/frameworks/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/frameworks/MCP-SERVER.md)
---
> Model Context Protocol server with 16 intelligent tools
> Yönlendirme, önbellek, sıkıştırma, bellek, yetenekler, proxy, havuz, Radar ve bağlam kaynak işlemleri genelinde 110 araç içeren Model Context Protocol (MCP) sunucusu.
>
> Doğruluk kaynağı: `open-sse/mcp-server/server.ts` dosyası `countUniqueMcpTools()` ile **110 benzersiz araç** hesaplar: 45 kurallı tanım (altı CCR yaşam döngüsü aracı, ajan yetenekleri üçlüsü, `omniroute_radar_catalog` ve `omniroute_x_search` dahil), artı bellek (3), yetenekler (4), GitHub yetenekleri (3), havuz (6), oyunlaştırma (8), eklentiler (8), Notion (6), Obsidian (22), yerel külliyat (3) ve iki RTK sıkıştırma aracı.
## Kurulum
OmniRoute MCP is built-in. Start it with:
OmniRoute MCP yerleşik olarak gelir. Şununla başlatın:
```bash
omniroute --mcp
```
Or via the open-sse transport:
Veya open-sse taşıması aracılığıyla:
```bash
# HTTP streamable transport (port 20130)
omniroute --dev # MCP auto-starts on /mcp endpoint
# HTTP akış taşıması (port 20130)
omniroute --dev # MCP /mcp uç noktasında otomatik başlar
```
## IDE Configuration
## Taşıma Modları (Transports)
See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
MCP sunucusu, tümü aynı `createMcpServer()` fabrikası tarafından desteklenen üç taşıma protokolü sunar:
| Taşıma | Konum | Ne zaman kullanılır |
| :---------------- | :------------------------------------------ | :--------------------------------------------------- |
| `stdio` | `open-sse/mcp-server/server.ts` | IDE entegrasyonları (Claude Desktop, Cursor vb.) |
| `sse` | `httpTransport` ile `POST/GET /api/mcp/sse` | Olay akışına ihtiyaç duyan tarayıcı/ajan istemcileri |
| `streamable-http` | `POST/GET/DELETE /api/mcp/stream` | Çoklu oturumlu HTTP istemcileri (`mcp-session-id`) |
Etkin HTTP taşıması (`sse` veya `streamable-http`) `mcpTransport` ayarıyla seçilir. Taşıma modunu değiştirmek diğer taşımadaki mevcut oturumları kapatır.
### Uzaktan Erişim (`manage` Kapsamı)
`/api/mcp/*` LOCAL_ONLY katmanındadır (`src/server/authz/routeGuard.ts`) — varsayılan olarak yalnızca yerel döngü ana bilgisayarları (`localhost`, `127.0.0.1`, `::1`) erişebilir. v3.8.2'den bu yana, yerel olmayan istemciler `manage` kapsamına sahip bir `Authorization: Bearer <api-key>` anahtarı sunduklarında bağlanabilirler. Bu, tünel, ters proxy veya genel ana bilgisayar adı üzerinden uzak MCP sunucusuna erişmenin tek yoludur.
```bash
# Uzak bir MCP istemcisinden bağlanın:
curl -i \
-H "Host: your-public-host.example" \
-H "Authorization: Bearer sk-…" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"my-client","version":"0"}}}' \
https://your-public-host.example/api/mcp/stream
```
---
## Essential Tools (8)
## Temel Araçlar (13) — Aşama 1
| Tool | Description |
| :------------------------------ | :--------------------------------------- |
| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
| `omniroute_list_combos` | All configured combos with models |
| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
| `omniroute_switch_combo` | Switch active combo by ID/name |
| `omniroute_check_quota` | Quota status per provider or all |
| `omniroute_route_request` | Send a chat completion through OmniRoute |
| `omniroute_cost_report` | Cost analytics for a time period |
| `omniroute_list_models_catalog` | Full model catalog with capabilities |
| Araç | Kapsamlar | Açıklama |
| :------------------------------ | :-------------------- | :------------------------------------------------------------ |
| `omniroute_get_health` | `read:health` | Çalışma süresi, bellek, devre kesiciler, hız sınırları, önbellek |
| `omniroute_list_combos` | `read:combos` | Stratejileriyle birlikte yapılandırılmış tüm kombolar |
| `omniroute_get_combo_metrics` | `read:combos` | Belirli bir kombo için performans metrikleri |
| `omniroute_switch_combo` | `write:combos` | Bir komboyu etkinleştirme veya devre dışı bırakma |
| `omniroute_create_combo` | `write:combos` | Doğrulanmış bir kombo oluşturma |
| `omniroute_check_quota` | `read:quota` | Kullanılan/toplam kota, kalan yüzde, sıfırlanma süresi |
| `omniroute_route_request` | `execute:completions` | OmniRoute yönlendirmesi üzerinden sohbet tamamlama gönderme |
| `omniroute_cost_report` | `read:usage` | Döneme göre maliyet raporu (oturum/gün/hafta/ay) |
| `omniroute_list_models_catalog` | `read:models` | Yetenekler, durum ve fiyatlandırma ile tam model kataloğu |
| `omniroute_radar_catalog` | `read:radar` | Yerel imzalı Radar kataloğu; isteğe bağlı filtreler |
| `omniroute_tool_search` | `read:tools` | Kayıtlı MCP kataloğundan araçları keşfetme |
| `omniroute_web_search` | `execute:search` | Yapılandırılmış sağlayıcılar üzerinden web araması |
| `omniroute_x_search` | `execute:search` | SuperGrok / xAI üzerinden X (Twitter) araması |
| `omniroute_web_fetch` | `execute:search` | Yapılandırılmış getirme sağlayıcıları üzerinden web içeriği alma |
## Advanced Tools (8)
## Gelişmiş Araçlar (11) — Aşama 2
| Tool | Description |
| :--------------------------------- | :---------------------------------------------------------- |
| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
| `omniroute_explain_route` | Explain a past routing decision |
| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
| Araç | Kapsamlar | Açıklama |
| :--------------------------------- | :----------------------------------- | :------------------------------------------------------------------------------------ |
| `omniroute_simulate_route` | `read:health`, `read:combos` | Geri dönüş ağacı ile yönlendirme simülasyonu (kuru çalıştırma) |
| `omniroute_set_budget_guard` | `write:budget` | Düşürme/engelleme/uyarı eylemi ile oturum bütçesi koruması |
| `omniroute_set_routing_strategy` | `write:combos` | Çalışma zamanında kombo stratejisini güncelleme |
| `omniroute_set_resilience_profile` | `write:resilience` | `aggressive` / `balanced` / `conservative` dayanıklılık önayarı uygulama |
| `omniroute_test_combo` | `execute:completions`, `read:combos` | Gerçek bir çağrı kullanarak kombodaki her sağlayıcıyı canlı test etme |
| `omniroute_get_provider_metrics` | `read:health` | p50/p95/p99 gecikme ve devre kesici durumu ile sağlayıcı başına metrikler |
| `omniroute_best_combo_for_task` | `read:combos`, `read:health` | Bütçe/gecikme kısıtlamalarıyla görev türüne göre kombo önerme |
| `omniroute_explain_route` | `read:health`, `read:usage` | Bir isteğin neden belirli bir sağlayıcıya yönlendirildiğini açıklama |
| `omniroute_get_session_snapshot` | `read:usage` | Tam oturum anlık görüntüsü: maliyet, tokenlar, modeller, hatalar |
| `omniroute_db_health_check` | `read:health`, `write:resilience` | Veritabanı sapmalarını tanılama (ve isteğe bağlı otomatik onarma) |
| `omniroute_sync_pricing` | `pricing:write` | Dış kaynaklardan (LiteLLM) fiyatlandırma verilerini senkronize etme |
## Authentication
---
MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
## Bağlam, Bellek ve Yetenek Araçları
| Scope | Tools |
| :------------- | :----------------------------------------------- |
| `read:health` | get_health, get_provider_metrics |
| `read:combos` | list_combos, get_combo_metrics |
| `write:combos` | switch_combo |
| `read:quota` | check_quota |
| `write:route` | route_request, simulate_route, test_combo |
| `read:usage` | cost_report, get_session_snapshot, explain_route |
| `write:config` | set_budget_guard, set_resilience_profile |
| `read:models` | list_models_catalog, best_combo_for_task |
## Audit Logging
Every tool call is logged to `mcp_tool_audit` with:
- Tool name, arguments, result
- Duration (ms), success/failure
- API key hash, timestamp
## Files
| File | Purpose |
| :------------------------------------------- | :------------------------------------------ |
| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
| `open-sse/mcp-server/auth.ts` | API key + scope validation |
| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
- **Bellek Araçları:** `omniroute_memory_search`, `omniroute_memory_store`, `omniroute_memory_delete`
- **Yetenek Araçları:** `omniroute_skill_execute`, `omniroute_skill_list`, `omniroute_skill_register`
- **Bağlam Kaynakları:** Notion (`omniroute_notion_*`), Obsidian (`omniroute_obsidian_*`), Yerel Külliyat (`omniroute_corpus_*`)

View File

@@ -1,23 +1,18 @@
# CLI-INTEGRATIONS (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../guides/CLI-INTEGRATIONS.md) · 🇸🇦 [ar](../../../ar/docs/guides/CLI-INTEGRATIONS.md) · 🇦🇿 [az](../../../az/docs/guides/CLI-INTEGRATIONS.md) · 🇧🇬 [bg](../../../bg/docs/guides/CLI-INTEGRATIONS.md) · 🇧🇩 [bn](../../../bn/docs/guides/CLI-INTEGRATIONS.md) · 🇨🇿 [cs](../../../cs/docs/guides/CLI-INTEGRATIONS.md) · 🇩🇰 [da](../../../da/docs/guides/CLI-INTEGRATIONS.md) · 🇩🇪 [de](../../../de/docs/guides/CLI-INTEGRATIONS.md) · 🇪🇸 [es](../../../es/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇷 [fa](../../../fa/docs/guides/CLI-INTEGRATIONS.md) · 🇫🇮 [fi](../../../fi/docs/guides/CLI-INTEGRATIONS.md) · 🇫🇷 [fr](../../../fr/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇳 [gu](../../../gu/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇱 [he](../../../he/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇳 [hi](../../../hi/docs/guides/CLI-INTEGRATIONS.md) · 🇭🇺 [hu](../../../hu/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇩 [id](../../../id/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇩 [in](../../../in/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇹 [it](../../../it/docs/guides/CLI-INTEGRATIONS.md) · 🇯🇵 [ja](../../../ja/docs/guides/CLI-INTEGRATIONS.md) · 🇰🇷 [ko](../../../ko/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇳 [mr](../../../mr/docs/guides/CLI-INTEGRATIONS.md) · 🇲🇾 [ms](../../../ms/docs/guides/CLI-INTEGRATIONS.md) · 🇳🇱 [nl](../../../nl/docs/guides/CLI-INTEGRATIONS.md) · 🇳🇴 [no](../../../no/docs/guides/CLI-INTEGRATIONS.md) · 🇵🇭 [phi](../../../phi/docs/guides/CLI-INTEGRATIONS.md) · 🇵🇱 [pl](../../../pl/docs/guides/CLI-INTEGRATIONS.md) · 🇵🇹 [pt](../../../pt/docs/guides/CLI-INTEGRATIONS.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/guides/CLI-INTEGRATIONS.md) · 🇷🇴 [ro](../../../ro/docs/guides/CLI-INTEGRATIONS.md) · 🇷🇺 [ru](../../../ru/docs/guides/CLI-INTEGRATIONS.md) · 🇸🇰 [sk](../../../sk/docs/guides/CLI-INTEGRATIONS.md) · 🇸🇪 [sv](../../../sv/docs/guides/CLI-INTEGRATIONS.md) · 🇰🇪 [sw](../../../sw/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇳 [ta](../../../ta/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇳 [te](../../../te/docs/guides/CLI-INTEGRATIONS.md) · 🇹🇭 [th](../../../th/docs/guides/CLI-INTEGRATIONS.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/guides/CLI-INTEGRATIONS.md) · 🇵🇰 [ur](../../../ur/docs/guides/CLI-INTEGRATIONS.md) · 🇻🇳 [vi](../../../vi/docs/guides/CLI-INTEGRATIONS.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/guides/CLI-INTEGRATIONS.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/guides/CLI-INTEGRATIONS.md)
---
---
title: "CLI Entegrasyonları — herhangi bir kodlama CLI'sını OmniRoute'a yönlendirin"
title: "CLI Entegrasyonları — Herhangi bir kodlama CLI'ını OmniRoute'a Bağlayın"
version: 3.8.50
lastUpdated: 2026-08-18
lastUpdated: 2026-08-23
---
# CLI Entegrasyonları
# CLI Entegrasyonları (Türkçe)
OmniRoute, bir kodlama CLI'sını (Codex, Claude Code, OpenCode, Cline, …) OmniRoute'u arka uç olarak kullanacak şekilde yapılandıran bir dizi `setup-*` komutu ile birlikte gelir — böylece araç **bir** uç noktaya bağlanır ve OmniRoute doğru sağlayıcıya otomatik olarak yönlendirir. Her komut, çalışan bir OmniRoute'tan (yerel veya uzaktan) **canlı** model kataloğunu okur ve aracın kendi yapılandırma dosyasını **sizin** makinenizde yazar. API anahtarı, aracın desteklediği her yerde bir ortam değişkeni ile referans alınır. Araç yerel bir ortam dosyasını kalıcı hale getiren komutlar aşağıda belirtilmiştir.
🌐 **Languages:** 🇺🇸 [English](../../../../docs/guides/CLI-INTEGRATIONS.md) · 🇸🇦 [ar](../../ar/docs/guides/CLI-INTEGRATIONS.md) · 🇧🇬 [bg](../../bg/docs/guides/CLI-INTEGRATIONS.md) · 🇧🇩 [bn](../../bn/docs/guides/CLI-INTEGRATIONS.md) · 🇨🇿 [cs](../../cs/docs/guides/CLI-INTEGRATIONS.md) · 🇩🇰 [da](../../da/docs/guides/CLI-INTEGRATIONS.md) · 🇩🇪 [de](../../de/docs/guides/CLI-INTEGRATIONS.md) · 🇪🇸 [es](../../es/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇷 [fa](../../fa/docs/guides/CLI-INTEGRATIONS.md) · 🇫🇮 [fi](../../fi/docs/guides/CLI-INTEGRATIONS.md) · 🇫🇷 [fr](../../fr/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇳 [gu](../../gu/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇱 [he](../../he/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇳 [hi](../../hi/docs/guides/CLI-INTEGRATIONS.md) · 🇭🇺 [hu](../../hu/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇩 [id](../../id/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇹 [it](../../it/docs/guides/CLI-INTEGRATIONS.md) · 🇯🇵 [ja](../../ja/docs/guides/CLI-INTEGRATIONS.md) · 🇰🇷 [ko](../../ko/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇳 [mr](../../mr/docs/guides/CLI-INTEGRATIONS.md) · 🇲🇾 [ms](../../ms/docs/guides/CLI-INTEGRATIONS.md) · 🇳🇱 [nl](../../nl/docs/guides/CLI-INTEGRATIONS.md) · 🇳🇴 [no](../../no/docs/guides/CLI-INTEGRATIONS.md) · 🇵🇭 [phi](../../phi/docs/guides/CLI-INTEGRATIONS.md) · 🇵🇱 [pl](../../pl/docs/guides/CLI-INTEGRATIONS.md) · 🇵🇹 [pt](../../pt/docs/guides/CLI-INTEGRATIONS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/guides/CLI-INTEGRATIONS.md) · 🇷🇴 [ro](../../ro/docs/guides/CLI-INTEGRATIONS.md) · 🇷🇺 [ru](../../ru/docs/guides/CLI-INTEGRATIONS.md) · 🇸🇰 [sk](../../sk/docs/guides/CLI-INTEGRATIONS.md) · 🇸🇪 [sv](../../sv/docs/guides/CLI-INTEGRATIONS.md) · 🇰🇪 [sw](../../sw/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇳 [ta](../../ta/docs/guides/CLI-INTEGRATIONS.md) · 🇮🇳 [te](../../te/docs/guides/CLI-INTEGRATIONS.md) · 🇹🇭 [th](../../th/docs/guides/CLI-INTEGRATIONS.md) · 🇹🇷 [tr](../../tr/docs/guides/CLI-INTEGRATIONS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/guides/CLI-INTEGRATIONS.md) · 🇵🇰 [ur](../../ur/docs/guides/CLI-INTEGRATIONS.md) · 🇻🇳 [vi](../../vi/docs/guides/CLI-INTEGRATIONS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/guides/CLI-INTEGRATIONS.md)
Ayrıca, herhangi bir yapılandırma yazmadan doğru ortamı enjekte eden `omniroute run <target>` adlı genel bir başlatıcı da vardır; bu, `claude`, `codex`, `aider`, `goose`, `opencode`, `qwen` veya `gemini`'yi başlatır. Hedefler ve takma adları, kanonik manifestodan `bin/cli/cli-manifest.mjs` gelir (`claude-code|cc|anthropic`, `codex-cli|openai-codex|openai`, `goose-cli`, `open-code`, `qwen-code`, `gemini-cli`), ve `omniroute completion` aynı manifestodan türetilmiş hedef kelimeleri sunar. Eski her araç için başlatıcılar — `omniroute launch` (Claude Code) ve `omniroute launch-codex` (Codex) — kullanılabilir durumda kalır.
---
Sağlayıcı kaydı, aynı yerel/uzaktan bağlamdan mevcuttur. Aşağıdaki API-first komutları, yönetim kimlik doğrulamasını sağlayıcı kimlik bilgilerinden ayrı tutar ve asla yapılandırılmış çıktıda bir kimlik bilgisi yazdırmaz:
OmniRoute, kodlama CLI araçlarını (Codex, Claude Code, OpenCode, Cline vb.) arka uç olarak OmniRoute'u kullanacak şekilde yapılandıran bir dizi `setup-*` komutu sunar — böylece araç **tek bir** uç nokta ile konuşur ve OmniRoute otomatik geri dönüş ile doğru sağlayıcıya yönlendirir.
Ayrıca hiçbir yapılandırma dosyası yazmadan doğru ortam değişkenleriyle `claude`, `codex`, `aider`, `goose`, `opencode`, `qwen` veya `gemini` başlatan genel bir çalıştırıcı vardır: `omniroute run <target>`.
```bash
omniroute providers add glm --credential-env GLM_API_KEY --name work
@@ -27,246 +22,23 @@ omniroute providers edit <connection-id> --default-model glm/glm-5.2
omniroute providers remove <connection-id> --yes
```
Betikler için `--credential-stdin` veya `--credential-env` tercih edilmelidir; `--credential` kontrollü yerel kullanım için saklanmıştır. `providers remove`, etkileşimli olmayan bir terminalde `--yes` gerektirir ve beş komut da aktif bağlamı veya global `--base-url`/`--api-key` seçeneklerini dikkate alır.
İki en zengin entegrasyonun bir kerelik, el yazısı ile yapılan temel kurulumu için, her araç için derinlemesine incelemelere bakın:
- [Claude Code yapılandırması](./CLAUDE-CODE-CONFIGURATION.md)
- [Codex CLI yapılandırması](./CODEX-CLI-CONFIGURATION.md)
- [Uzaktan Mod](./REMOTE-MODE.md) — dizüstü bilgisayarınızdan uzaktan bir OmniRoute'u yönetin (VPS / Tailnet)
- [VS Code Copilot Chat](./VSCODE-COPILOT.md) — OmniCopilot uzantısı; ayrıca bu `setup-*` komutlarını editör içinde sizin için çalıştırabilir
---
## Ana tablo
## Ana Kurulum Tablosu
Her komut, **aktif bağlamı** ( `omniroute connect` ile ayarlanmış, bkz. [Uzaktan Mod](./REMOTE-MODE.md)) veya açık `--remote <url> --api-key <key>` bayraklarını dikkate alır. Aşağıdaki "Yerel vs uzaktan" ifadesi: bayraksız olarak `http://localhost:20128`'i hedef alır; `--remote` ile (veya aktif bir uzaktan bağlam ile) o sunucudan katalogu alır ve yapılandırmayı yerel olarak yazar.
| Komut | Araç | Yazdığı şey | Ana bayraklar | Yerel vs uzaktan |
| -------------------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- |
| `omniroute setup-codex` | OpenAI Codex CLI | `~/.codex/<name>.config.toml` — uyumlu metin modeli başına bir profil (`codex --profile <name>`) | `--remote` `--api-key` `--only` `--dry-run` `--port` `--codex-home` | Her ikisi |
| `omniroute setup-claude` | Claude Code | `~/.claude/profiles/<name>/settings.json` — eşleşen model başına bir profil (`CLAUDE_CONFIG_DIR`) | `--remote` `--api-key` `--only` `--dry-run` `--port` `--claude-home` | Her ikisi |
| `omniroute setup-opencode` | OpenCode (openai-uyumlu) | `~/.config/opencode/opencode.json` — her katalog modeline sahip `omniroute` sağlayıcısı (`opencode -m omniroute/<model>`) | `--remote` `--api-key` `--only` `--model` `--dry-run` `--port` | Her ikisi |
| `omniroute setup-cline` | Cline | `~/.cline/data/{globalState,secrets}.json` (CLI modu) + VS Code uzantı ayarlarını yazdırır | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--cline-dir` | Her ikisi |
| `omniroute setup-kilo` | Kilo Code | `~/.local/share/kilo/auth.json` (CLI) + mevcutsa `kilocode.*`'u VS Code `settings.json` içine birleştirir | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--auth-path` `--vscode-settings` | Her ikisi |
| `omniroute setup-continue` | Continue / `cn` CLI | `~/.continue/config.yaml``provider: openai` modelleri, anahtar `${{ secrets.OMNIROUTE_API_KEY }}` aracılığıyla | `--remote` `--api-key` `--only` `--dry-run` `--port` `--config-path` | Her ikisi |
| `omniroute setup-cursor` | Cursor | Hiçbir şey — uygulama içindeki adımları yazdırır (Cursor yapılandırması opak SQLite) | `--remote` `--api-key` `--only` `--port` | Her ikisi |
| `omniroute setup-roo` | Roo Code | `~/.omniroute/roo-settings.json` (içe aktarma belgesi) + bir VS Code `settings.json` varsa `roo-cline.autoImportSettingsPath` ayarlar | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--import-path` `--vscode-settings` | Her ikisi |
| `omniroute setup-crush` | Crush | `~/.config/crush/crush.json``openai-uyumlu` sağlayıcı, anahtar `$OMNIROUTE_API_KEY` aracılığıyla | `--remote` `--api-key` `--only` `--dry-run` `--port` `--config-path` | Her ikisi |
| `omniroute setup-goose` | Goose | `~/.config/goose/config.yaml` (`GOOSE_PROVIDER`/`OPENAI_HOST`/`GOOSE_MODEL`) + ortam tarifini yazdırır | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--config-path` | Her ikisi |
| `omniroute setup-aider` | Aider | `~/.aider.conf.yml` (`openai-api-base` + `model: openai/<id>`) + ortam tarifini yazdırır | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--config-path` | Her ikisi |
| `omniroute setup-qwen` | Qwen Code | `~/.qwen/settings.json` — V4 `modelProviders.openai` dizisi + `OMNIROUTE_API_KEY` `~/.qwen/.env` içinde | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--config-path` `--env-path` | Her ikisi |
| `omniroute run <target>` | Çalışma başlatma (genel) | Hiçbir şey — doğru ortam ve argümanlarla `claude`/`codex`/`aider`/`goose`/`opencode`/`qwen`/`gemini` başlatır; Qwen ve Gemini geçici izole bir ev kullanır | `--remote` `--base-url` `--context` `--provider` `--model` `--api-key` `--api-key-env` `--dry-run` `--json` `--port` `--profile` `--token` | Her ikisi |
| `omniroute launch` | Claude Code | Hiçbir şey — `ANTHROPIC_BASE_URL`/`ANTHROPIC_AUTH_TOKEN` ile `claude` başlatır | `--remote` `--api-key` `--token` `--profile` `--port` | Her ikisi |
| `omniroute launch-codex` | OpenAI Codex CLI | Hiçbir şey — `-c` bayrakları aracılığıyla `omniroute` sağlayıcısı ile `codex` başlatır | `--remote` `--api-key` `--profile` (`-p`) `--port` | Her ikisi |
Bayraklar hakkında notlar (komut kaynağında doğrulanmıştır):
- `--remote <url>` — uzaktan bir OmniRoute'tan katalogu alır ( `--port` ve aktif bağlamı geçersiz kılar). `--api-key <key>` o sunucu için kimlik bilgilerini sağlar (varsayılan olarak `OMNIROUTE_API_KEY` ortam değişkenine veya aktif bağlamın jetonuna ayarlanır).
- `--only <patterns>` — virgülle ayrılmış alt dizeler; yalnızca eşleşen model kimliklerini tutar (örneğin, `--only glm,kimi`). `setup-codex`, `setup-claude`, `setup-opencode`, `setup-continue`, `setup-cursor`, `setup-crush` üzerinde mevcuttur.
- `--dry-run` — dosya sistemine dokunmadan yazılacak olanı tam olarak yazdırır. Her `setup-*` komutunda mevcuttur **hariç** `setup-cursor` (asla bir dosya yazmaz).
- `--model <id>` — otomatik model keşfi olmayan araçlar için gereklidir (veya etkileşimli olarak seçilir): Cline, Kilo, Roo, Goose, Qwen, Aider. Bu araçlar ayrıca etkileşimli çalıştırmalar için `--yes`'i kabul eder (bu durumda `--model` gereklidir). `setup-opencode`, varsayılan üst düzey modeli ayarlamak için `--model` alır.
- `--model <id>` `omniroute run` üzerinde manifestonun her hedef için bağlantısını takip eder (`bin/cli/cli-manifest.mjs`): **aider** `--model openai/<id>` alır ve **opencode** `--model omniroute/<id>` (ön ek yalnızca id zaten taşımıyorsa eklenir); **qwen** ve **gemini** id'yi olduğu gibi alır; **claude** bunu `ANTHROPIC_MODEL` aracılığıyla alır, **goose** `GOOSE_MODEL` aracılığıyla ve **codex** `-c model_providers.omniroute.*` argümanları aracılığıyla alır. **Qwen, yalnızca `--model` gerektiren tek çalıştırma hedefidir**`omniroute run qwen` olmadan çıkış kodu `2` ile açık bir hata verir.
- `--port <port>` — yerel OmniRoute portu (varsayılan `20128`, `--remote` ayarlandığında göz ardı edilir). Tüm `setup-*` ve her iki başlatıcıda mevcuttur.
- `omniroute run` çıkış kodları: çocuk CLI'nın kendi çıkış kodu olduğu gibi iletilir; `2` = geçersiz argümanlar (desteklenmeyen hedef, eksik gerekli `--model`, konteyner koruması); `127` = hedef ikili `PATH` içinde değil; `130`/`143`/`129` başlatma `SIGINT`/`SIGTERM`/`SIGHUP` ile sonlandığında; `1` = diğer çalışma zamanı başlatma hatası.
- İki başlatıcı (`launch`, `launch-codex`) `setup-claude` / `setup-codex` tarafından yazılan bir profili seçmek için `--profile <name>` alır, ayrıca temel `claude` / `codex` ikili için geçiş argümanları alır.
Etkileşimli seçim aracı, kurulum tarifleri ile de paylaşılmaktadır:
```bash
# Aktif yerel veya uzaktan model kataloğundan seçin ve hedefi yapılandırın.
omniroute configure claude
omniroute configure opencode --provider glm
omniroute configure qwen --model qwen/qwen3.8-max-preview --yes
```
`configure` şu anda `codex`, `claude`, `opencode`, `qwen`, `aider`, `goose`, `cline`, `continue` ve `kilo` için test edilen tariflere devreder. Sadece IDE, MITM ve rehber olarak katalog girişleri açıkça `setup-*`/manuel akışlar olarak kalır ve başlatılabilir hedefler olarak sunulmaz.
> `setup-opencode`, **hafif openai-uyumlu** OpenCode entegrasyonudur.
> Ayrıca daha zengin bir eklenti entegrasyonu vardır — `omniroute setup opencode` — bu, `@omniroute/opencode-plugin`'i yükler. Bunlar farklı komutlardır; yukarıdaki tablo `setup-opencode`'yi belgeler.
---
## Yerel kullanım
`localhost:20128` üzerinde OmniRoute çalışırken, sadece aracınız için kurulum komutunu çalıştırın. Katalog yerel sunucudan alınır.
```bash
# Codex: eşleşen model başına ~/.codex/ içine bir profil yaz
omniroute setup-codex
codex --profile glm52 # oluşturulan profili kullan
# Claude Code: model başına profiller yaz, sonra birini başlat
omniroute setup-claude
omniroute launch --profile glm52
# OpenCode: tüm katalog modelleri ile openai uyumlu sağlayıcıyı yaz
omniroute setup-opencode
export OMNIROUTE_API_KEY=sk-... # {env:OMNIROUTE_API_KEY} ile referans alınır, asla diskte değil
opencode -m omniroute/glm/glm-5.2 "..."
# Otomatik keşif yapmayan araçlar açık bir model gerektirir:
omniroute setup-aider --model glm/glm-5.2
omniroute setup-qwen --model qwen/qwen3.8-max-preview
# Hiçbir şey yazmadan önizleme:
omniroute setup-continue --dry-run
```
Hiçbir yapılandırma yazmadan başlatın (sadece ortam enjekte etme):
```bash
omniroute launch # Claude Code → yerel OmniRoute
omniroute launch-codex # Codex CLI → yerel OmniRoute
omniroute launch-codex --profile glm52
omniroute run claude --model openai/gpt-5.4
omniroute run codex --model openai/gpt-5.4 --dry-run --json
omniroute run aider --model glm/glm-5.2 -- --message "reply OK"
omniroute run goose --model glm/glm-5.2
omniroute run opencode --model glm/glm-5.2 -- run "reply OK"
omniroute run qwen --model glm/glm-5.2 -- -p "reply OK"
omniroute run gemini --model glm/glm-5.2 -- --skip-trust -p "reply OK"
# Açık komut yolu: -- sonrası gelen her şeyi geçirin
omniroute run claude -- --print-system-prompt "bu farkı gözden geçir"
```
---
## Uzaktan kullanım
Herhangi bir kurulum komutunu `--remote` + `--api-key` ile uzaktaki bir OmniRoute'a yönlendirin. Katalog uzaktan alınır; yapılandırma yerel makinenizde yazılır.
```bash
# Uzaktaki bir VPS'ye karşı OpenCode, yalnızca glm/kimi modellerini tut
omniroute setup-opencode --remote http://192.168.0.15:20128 --api-key oma_live_xxx \
--only glm,kimi
opencode -m omniroute/glm/glm-5.2 "..." # önce OMNIROUTE_API_KEY'i dışa aktar
# Uzaktan bir katalogdan Codex profilleri
omniroute setup-codex --remote http://192.168.0.15:20128 --api-key oma_live_xxx
# CLI'yi doğrudan uzaktaki sunucuya karşı başlat
omniroute launch --remote http://192.168.0.15:20128 --api-key oma_live_xxx
omniroute launch-codex --remote http://192.168.0.15:20128 --api-key oma_live_xxx
```
Her seferinde `--remote`/`--api-key` geçmek yerine, bir kez giriş yapın ve **aktif bağlam** bunları otomatik olarak sağlasın:
```bash
omniroute connect 192.168.0.15 # kapsamlı bir token oluşturur, bağlamı saklar
omniroute setup-codex # ← artık uzaktan katalogu kullanır
omniroute setup-opencode # ← aynı
omniroute launch # ← Claude Code uzakta
```
Bağlamlar, kapsamlar ve token yönetimi için [Uzaktan Mod](./REMOTE-MODE.md) sayfasına bakın.
---
## Temel URL konvansiyonları (hangi araçlar `/v1` ister)
OmniRoute, OpenAI yüzeyini `/v1`'de, Anthropic yüzeyini kök dizinde ve yerel Gemini yüzeyini `/v1beta`'da sunar. Her entegrasyon, aracının beklediği forma bağlıdır (komut kaynağında doğrulanmıştır):
| Entegrasyon | Yazılan Temel URL | `/v1`? |
| -------------------------------------------------------------------------- | ----------------- | -------------------------------------------- |
| `setup-cline` (`openAiBaseUrl`) | kök | Hayır — Cline `/v1/chat/completions` ekler |
| `setup-goose` (`OPENAI_HOST`) | kök | Hayır — Goose yolu ekler |
| `setup-aider` (`OPENAI_API_BASE`) | kök | Hayır — LiteLLM `/v1/chat/completions` ekler |
| `setup-kilo`, `setup-roo`, `setup-continue`, `setup-crush`, `setup-cursor` | `/v1` ile | Evet |
| `setup-claude` (`ANTHROPIC_BASE_URL`), `launch` | kök | Hayır — Claude Code `/v1/messages` ekler |
| `setup-codex`, `launch-codex` (`model_providers.omniroute.base_url`) | `/v1` ile | Evet |
| `setup-qwen` (`modelProviders.openai[].baseUrl`) | `/v1` ile | Evet |
| `run gemini` (`GOOGLE_GEMINI_BASE_URL`) | kök | Hayır — SDK `/v1beta/models/…` ekler |
---
## Yerel bağımlılıkları güncellemede tutmak: `--include=optional`
`omniroute update` ile güncelleme yaptığınızda (onayladıktan sonra veya `--apply` ile),
OmniRoute, `--include=optional` seçeneği ile yüklemeyi gerçekleştirir:
```bash
npm install -g omniroute@latest --include=optional
```
Bu, `omniroute update` komutuna geçirdiğiniz bir bayrak **değildir** — her zaman
güncelleyici tarafından uygulanır. `optionalDependencies` (`better-sqlite3`, `keytar`,
`tls-client`, LLMLingua SLM yığını) güncelleme sırasında hayatta kalmasını garanti eder,
npm yapılandırmanızda `omit=optional` ayarı olsa bile, bu durumda yerel SQLite
sürücüsü ve OS-anahtar bağıntısı sessizce kaldırılır. Uygulamadan önce tam komutu
önizlemek için:
```bash
omniroute update --dry-run
# [DRY RUN] Şu komut çalıştırılacak: npm install -g omniroute@latest --include=optional
```
Diğer `omniroute update` bayrakları (kaynakta doğrulanmıştır): `--check` (eskiyse 1 ile çık),
`--apply` (sormadan yükle), `--changelog`, `--no-backup`, `--yes`.
---
## Google Gemini CLI `omniroute run gemini` ile
`@google/gemini-cli` 0.50.0 ile doğrulanan sözleşme: CLI, `GOOGLE_GEMINI_BASE_URL`'yi
kabul eder ve `POST /v1beta/models/<model>:generateContent`
(ve `:streamGenerateContent?alt=sse`) talep eder — tam olarak OmniRoute'un yerel
Gemini yüzeyi (`/v1beta`). `omniroute run gemini` bunu otomatik olarak bağlar:
- `GOOGLE_GEMINI_BASE_URL` → aktif OmniRoute temel URL'si (kök, `/v1` yok);
- `GEMINI_API_KEY` → çözümlenen OmniRoute kimlik bilgisi (seçenek/env/bağlam);
- **geçici izole `GEMINI_CLI_HOME`** `.gemini/settings.json` dosyası
`gemini-api-key` kimlik doğrulamasını seçer, böylece saklanan Google OAuth oturumu
(Kod Yardımcı) asla OmniRoute yönlendirmeli başlatmayı geçersiz kılmaz — çıkıştan sonra
kaldırılır;
- **env hijyeni**: çocuk ortamı `GOOGLE_API_KEY`,
`GOOGLE_GENAI_USE_VERTEXAI` ve `GOOGLE_GENAI_USE_GCA`'dan arındırılır (bu
kimlik doğrulamasını Vertex/Kod Yardımcıya yönlendirebilir), ve `GEMINI_DEFAULT_AUTH_TYPE=gemini-api-key`
bir yedek olarak ayarlanır — diğer `run` hedefleri kendi çelişen değişkenleri için
aynı muameleyi alır;
- `--model <id>` enjeksiyonu `--provider`/`--model`'dan.
```bash
omniroute run gemini --model glm/glm-5.2 -- --skip-trust -p "hello"
```
Gemini'nin çalışma alanı güvenlik koruması hala başsız modda geçerlidir — `--skip-trust`
geçirin (veya dizini etkileşimli olarak güvenilir hale getirin); başlatıcı bunu
kasıtlı olarak atlamaz. Bu başlatıcı, **ACP kaydı** (`src/lib/acp/registry.ts`, `gemini --acp`)
ile farklıdır, bu hala `/dashboard/acp-agents` için ajan-protokol entegrasyonudur.
---
## Gerçek duman taraması (isteğe bağlı)
Deterministik başlatma planı regresyon testleri CI'da (`tests/unit/cli/run-command.test.ts`,
`tests/unit/cli/run-execution.test.ts`). GERÇEK ikili dosyaları GERÇEK
OmniRoute sunucusuna karşı doğrulamak için, `tests/integration/upstream-cli-smoke.int.test.ts`
adresinde isteğe bağlı bir sistem bulunmaktadır. Bu otomatik olarak çalışmaz
(her alt test, `RUN_CLI_SMOKE=1` ayarı yapılmadıkça atlanır), kimlik bilgilerini
çevre değişkeni ADI ile iletir (değer ile değil), anahtar biçimindeki dizeleri
herhangi bir kaydedilmiş çıktıda sansürler, ikili dosyası yüklü olmayan hedefleri
atlar ve hataları kimlik doğrulama / yukarı akış / yapılandırma olarak sınıflandırır,
basit bir boolean yerine:
```bash
RUN_CLI_SMOKE=1 \
OMNIROUTE_SMOKE_BASE_URL="http://localhost:20128" \
OMNIROUTE_SMOKE_MODEL="<provider/model>" \
OMNIROUTE_SMOKE_API_KEY_ENV="OMNIROUTE_API_KEY" \
node --import tsx/esm --test tests/integration/upstream-cli-smoke.int.test.ts
```
İsteğe bağlı: `OMNIROUTE_SMOKE_TARGETS="codex,opencode,qwen"` taramayı kısıtlar;
`OMNIROUTE_SMOKE_TIMEOUT_MS` her hedef için 120s zaman aşımını geçersiz kılar.
---
## Ayrıca bakınız
- [Claude Code yapılandırması](./CLAUDE-CODE-CONFIGURATION.md) — daha derin bir Claude Code kılavuzu
- [Codex CLI yapılandırması](./CODEX-CLI-CONFIGURATION.md) — bir kerelik `[model_providers.omniroute]` temel kurulumu
- [Uzaktan Mod](./REMOTE-MODE.md) — bağlamlar, kapsamlı erişim jetonları, uzaktan bir sunucuyu yönetme
- [CLI Araçları referansı](../reference/CLI-TOOLS.md) — desteklenen araçların tam kataloğu + kontrol paneli sayfaları
- [Kurulum Kılavuzu](./SETUP_GUIDE.md) — kurulum yöntemleri ve ilk çalışma eğitimi
| Komut | Araç | Ne Yazar | Temel Bayraklar | Yerel vs Uzak |
| -------------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | --------------- |
| `omniroute setup-codex` | OpenAI Codex CLI | `~/.codex/<name>.config.toml` — uyumlu model başına bir profil (`codex --profile <name>`) | `--remote` `--api-key` `--only` `--dry-run` `--port` `--codex-home` | Her ikisi de |
| `omniroute setup-claude` | Claude Code | `~/.claude/profiles/<name>/settings.json` — eşleşen model başına bir profil (`CLAUDE_CONFIG_DIR`) | `--remote` `--api-key` `--only` `--dry-run` `--port` `--claude-home` | Her ikisi de |
| `omniroute setup-opencode` | OpenCode (openai-compatible) | `~/.config/opencode/opencode.json` — katalogdaki her modelle `omniroute` sağlayıcısı (`opencode -m omniroute/<model>`) | `--remote` `--api-key` `--only` `--model` `--dry-run` `--port` | Her ikisi de |
| `omniroute setup-cline` | Cline | `~/.cline/data/{globalState,secrets}.json` (CLI modu) + VS Code eklenti ayarlarını yazdırır | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--cline-dir` | Her ikisi de |
| `omniroute setup-kilo` | Kilo Code | `~/.local/share/kilo/auth.json` (CLI) + varsa VS Code `settings.json` içine `kilocode.*` birleştirir | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--auth-path` `--vscode-settings` | Her ikisi de |
| `omniroute setup-continue` | Continue / `cn` CLI | `~/.continue/config.yaml``provider: openai` modelleri, anahtar `${{ secrets.OMNIROUTE_API_KEY }}` üzerinden | `--remote` `--api-key` `--only` `--dry-run` `--port` `--config-path` | Her ikisi de |
| `omniroute setup-cursor` | Cursor | Hiçbir dosya yazmaz — uygulama içi adımları konsola yazdırır | `--remote` `--api-key` `--only` `--port` | Her ikisi de |
| `omniroute setup-roo` | Roo Code | `~/.omniroute/roo-settings.json` (içe aktarma belgesi) | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--import-path` `--vscode-settings` | Her ikisi de |
| `omniroute setup-goose` | Goose | `~/.config/goose/config.yaml` (`GOOSE_PROVIDER`/`OPENAI_HOST`/`GOOSE_MODEL`) | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--config-path` | Her ikisi de |
| `omniroute setup-aider` | Aider | `~/.aider.conf.yml` (`openai-api-base` + `model: openai/<id>`) | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--config-path` | Her ikisi de |
| `omniroute setup-qwen` | Qwen Code | `~/.qwen/settings.json` — V4 `modelProviders.openai` dizisi | `--remote` `--api-key` `--model` `--yes` `--dry-run` `--port` `--config-path` `--env-path` | Her ikisi de |
| `omniroute run <target>` | Doğrudan Başlatma (Genel) | Dosya yazmaz — doğru ortam değişkenleriyle hedef aracı doğrudan başlatır | `--remote` `--base-url` `--context` `--provider` `--model` `--api-key` `--api-key-env` `--dry-run` `--json` `--port` `--profile` `--token` | Her ikisi de |
| `omniroute launch` | Claude Code | Dosya yazmaz — `ANTHROPIC_BASE_URL`/`ANTHROPIC_AUTH_TOKEN` ile `claude` başlatır | `--remote` `--api-key` `--token` `--profile` `--port` | Her ikisi de |
| `omniroute launch-codex` | OpenAI Codex CLI | Dosya yazmaz — `-c` parametreleri ile `codex` başlatır | `--remote` `--api-key` `--profile` (`-p`) `--port` | Her ikisi de |

View File

@@ -1,269 +1,51 @@
# OmniRoute — Dashboard Features Gallery (Türkçe)
---
title: "OmniRoute — Pano Özellikleri Galerisi"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇧🇩 [bn](../../bn/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇮🇷 [fa](../../fa/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇮🇳 [gu](../../gu/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇮🇳 [hi](../../hi/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇮🇳 [mr](../../mr/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇰🇪 [sw](../../sw/docs/FEATURES.md) · 🇮🇳 [ta](../../ta/docs/FEATURES.md) · 🇮🇳 [te](../../te/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇹🇷 [tr](../../tr/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇵🇰 [ur](../../ur/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md)
# OmniRoute — Pano Özellikleri Galerisi (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/guides/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/guides/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/guides/FEATURES.md) · 🇧🇩 [bn](../../bn/docs/guides/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/guides/FEATURES.md) · 🇩🇰 [da](../../da/docs/guides/FEATURES.md) · 🇩🇪 [de](../../de/docs/guides/FEATURES.md) · 🇪🇸 [es](../../es/docs/guides/FEATURES.md) · 🇮🇷 [fa](../../fa/docs/guides/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/guides/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/guides/FEATURES.md) · 🇮🇳 [gu](../../gu/docs/guides/FEATURES.md) · 🇮🇱 [he](../../he/docs/guides/FEATURES.md) · 🇮🇳 [hi](../../hi/docs/guides/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/guides/FEATURES.md) · 🇮🇩 [id](../../id/docs/guides/FEATURES.md) · 🇮🇹 [it](../../it/docs/guides/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/guides/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/guides/FEATURES.md) · 🇮🇳 [mr](../../mr/docs/guides/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/guides/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/guides/FEATURES.md) · 🇳🇴 [no](../../no/docs/guides/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/guides/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/guides/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/guides/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/guides/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/guides/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/guides/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/guides/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/guides/FEATURES.md) · 🇰🇪 [sw](../../sw/docs/guides/FEATURES.md) · 🇮🇳 [ta](../../ta/docs/guides/FEATURES.md) · 🇮🇳 [te](../../te/docs/guides/FEATURES.md) · 🇹🇭 [th](../../th/docs/guides/FEATURES.md) · 🇹🇷 [tr](../../tr/docs/guides/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/guides/FEATURES.md) · 🇵🇰 [ur](../../ur/docs/guides/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/guides/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/guides/FEATURES.md)
---
Visual guide to every section of the OmniRoute dashboard.
OmniRoute panosunun her bölümüne ilişkin görsel ve işlevsel kılavuz.
---
## 🔌 Providers
## ✨ v3.8.x Öne Çıkanlar
![Providers Dashboard](screenshots/01-providers.png)
- 🤖 **Auto Combo / Sıfır Yapılandırmalı Otomatik Yönlendirme**`auto/coding`, `auto/fast`, `auto/cheap`, `auto/offline`, `auto/smart`, `auto/lkgp` önekleri. 14 faktörlü puanlama motoru ve 4 küratörlü mod paketi (ship-fast, cost-saver, quality-first, offline-friendly) ile desteklenir.
- 🆕 **Command Code ve Z.AI sağlayıcıları** — Kota etiketleri ve model kataloğu ile birinci sınıf kayıt.
- 🎬 **KIE Medya Genişletmesi** — Video ve müzik üretimi modelleri dahil genişletilmiş katalog.
- 🔐 **Devin Kimlik Doğrulaması** — Masaüstü mevcut bir Devin API anahtarını içe aktarır; CLI yerel kimlik bilgilerini kullanır.
- 🆓 **Yeni Ücretsiz Sağlayıcılar** — LLM7, Lepton, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi vb.
- 🎨 **Cursor Tam OpenAI Eşitliği** — Araç çağırma (tool calls), akış ve uçtan uca oturum yönetimi.
- 📌 **Oturum Başına Yapışkan Yönlendirme (Sticky Routing)** — Codex oturumları turlar arasında aynı hesaba sabitlenir.
- 🔄 **Sıfırlama Duyarlı Yönlendirme Stratejisi** — Kombolar, kota penceresi en erken sıfırlanan hesapları tercih eder.
- 🩺 **Model Soğuma Süreleri Panosu** — Model bazlı kilitlenmeleri izleme ve kullanıcı arayüzünden manuel olarak yeniden etkinleştirme.
- 💻 **CLI Geliştirme Paketi**`omniroute providers`, `omniroute combos`, `omniroute doctor`, `omniroute setup` dahil 20'den fazla komut.
- 🧠 **Akıl Yürütme Tekrar Oynatma Önbelleği (Reasoning Replay Cache)** — Akıl yürütme izlerinin hibrit bellek içi + SQLite kalıcılığı.
---
## 🎨 Combos
## 🔌 Sağlayıcılar (Providers)
Create model routing combos with 13 strategies: priority, weighted, round-robin, random, least-used, cost-optimized, strict-random, auto, fill-first, p2c, lkgp, context-optimized, and **context-relay**. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
AI sağlayıcı bağlantılarını yönetin: OAuth sağlayıcıları (Claude Code, Codex), API anahtarı sağlayıcıları (Groq, DeepSeek, OpenRouter) ve ücretsiz sağlayıcılar (Qoder, Kiro).
Recent combo improvements:
## 🎨 Kombolar (Combos)
- **Structured combo builder** — create each step by selecting provider, model, and exact account/connection
- **Repeated provider support** — reuse the same provider many times in one combo as long as the `(provider, model, connection)` tuple is unique
- **Combo target health** — analytics and health surfaces now distinguish individual combo targets/steps instead of collapsing everything into model strings
- **Composite tier ordering** — `defaultTier -> fallbackTier` now influences runtime execution/fallback order for top-level combo steps
19 genel strateji ile model yönlendirme komboları oluşturun: priority, weighted, round-robin, context-relay, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, cache-optimized, **fusion** ve **pipeline**.
![Combos Dashboard](screenshots/02-combos.png)
## 📊 Analitik (Analytics)
---
Token tüketimi, maliyet tahminleri, etkinlik ısı haritaları, haftalık dağılım grafikleri ve sağlayıcı bazında ayrıntılarla kapsamlı kullanım analitiği.
## 📊 Analytics
## 🏥 Sistem Sağlığı (System Health)
Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
Gerçek zamanlı izleme: çalışma süresi, bellek, sürüm, gecikme yüzdelikleri (p50/p95/p99), önbellek istatistikleri, sağlayıcı devre kesici durumları ve kota izlenen aktif oturumlar.
![Analytics Dashboard](screenshots/03-analytics.png)
## 🛠️ CLI Araçları ve Ajanlar
---
## 🏥 System Health
Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, provider circuit breaker states, active quota-monitored sessions, and combo target health.
![Health Dashboard](screenshots/04-health.png)
---
## 🔧 Translator Playground
Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
![Translator Playground](screenshots/05-translator.png)
---
## 🎮 Model Playground _(v2.0.9+)_
Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
---
## 🎨 Themes _(v2.0.5+)_
Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
---
## ⚙️ Settings
Comprehensive settings panel with tabs:
- **General** — System storage, backup management (export/import database)
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
- **Routing** — Model aliases, background task degradation
- **Resilience** — Rate limit persistence, circuit breaker tuning, auto-disable banned accounts, provider expiration monitoring, **Context Relay** handoff threshold and summary model configuration
- **Advanced** — Configuration overrides, configuration audit trail, fallback degradation mode
![Settings Dashboard](screenshots/06-settings.png)
---
## 🔧 CLI Tools
One-click configuration for AI coding tools: Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
![CLI Tools Dashboard](screenshots/07-cli-tools.png)
---
## 🤖 CLI Agents _(v2.0.11+)_
Dashboard for discovering and managing CLI agents. Shows a grid of 17 built-in agents (Codex, Claude, Goose, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp, **Windsurf**, **Devin CLI**, **Kimi Coding**, **Command Code**) with:
- **Installation status** — Installed / Not Found with version detection
- **Protocol badges** — stdio, HTTP, etc.
- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
---
## 🔗 Context Relay _(v3.5.5+)_
A combo strategy that preserves session continuity when account rotation happens mid-conversation. Before the active account is exhausted, OmniRoute generates a structured handoff summary in the background. After the next request resolves to a different account, the summary is injected as a system message so the new account continues with full context.
Configurable via combo-level or global settings:
- **Handoff Threshold** — Quota usage percentage that triggers summary generation (default 85%)
- **Max Messages For Summary** — How much recent history to condense
- **Summary Model** — Optional override model for generating the handoff summary
Currently supports Codex account rotation. See [Context Relay documentation](features/context-relay.md).
---
## 🛡️ Proxy Hardening _(v3.5.5+)_
Comprehensive proxy configuration enforcement across the entire request pipeline:
- **Token Health Check** — Background OAuth refresh now resolves proxy config per connection, preventing failures in proxy-required environments
- **API Key Validation** — Provider key validation (`POST /api/providers/validate`) routes through `runWithProxyContext`, honoring provider-level and global proxy settings
- **undici Dispatcher Fix** — Proxy dispatchers use undici's own fetch implementation instead of Node's built-in fetch, resolving `invalid onRequestStart method` errors on Node.js 22
- **Node.js Version Detection** — Login page proactively detects incompatible Node.js versions (24+) and displays a warning banner with instructions to use Node 22 LTS
---
## 📧 Email Privacy Masking _(v3.5.6+)_
OAuth account emails are now masked in the provider dashboard (e.g. `di*****@g****.com`) to prevent accidental exposure when sharing screenshots or recording demos. The full email address remains accessible via hover tooltip (`title` attribute).
---
## 👁️ Model Visibility Toggle _(v3.5.6+)_
The provider page model list now includes:
- **Real-time search/filter bar** — Quickly find specific models
- **Per-model visibility toggle** (👁 icon) — Hidden models are grayed out and excluded from the `/v1/models` catalog
- **Active-count badge** (`N/M active`) — Shows at a glance how many models are enabled vs total
---
## 🔧 OAuth Env Repair _(v3.6.1+)_
One-click "Repair env" action for OAuth providers that restores missing environment variables and fixes broken auth state. Accessible from `Dashboard → Providers → [OAuth Provider] → Repair env`. Automatically detects and repairs:
- Missing OAuth client credentials
- Corrupted env file entries
- Backup path sanitization
---
## 🗑️ Uninstall / Full Uninstall _(v3.6.2+)_
Clean removal scripts for all installation methods:
| Command | Action |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |
| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |
---
## 🖼️ Media _(v2.0.3+)_
Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
---
## 📝 Request Logs
Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
![Usage Logs](screenshots/08-usage.png)
---
## 🌐 API Endpoint
Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloudflare Quick Tunnel integration and cloud proxy support for remote access.
![Endpoint Dashboard](screenshots/09-endpoint.png)
---
## 🔑 API Key Management
Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
---
## 📋 Audit Log
Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
---
## 🖥️ Desktop Application
Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
Key features:
- Server readiness polling (no blank screen on cold start)
- System tray with port management
- Content Security Policy
- Single-instance lock
- Auto-update on restart
- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
- **Graceful shutdown** — Electron `before-quit` shuts down Next.js cleanly, preventing SQLite WAL database locks (v3.6.2+)
📖 See [`electron/README.md`](../electron/README.md) for full documentation.
---
## 🌐 V1 WebSocket Bridge _(v3.6.6+)_
OmniRoute now supports **OpenAI-compatible WebSocket clients** via the `/v1/ws` upgrade endpoint. The custom `scripts/v1-ws-bridge.mjs` server wraps Next.js and upgrades WS connections to full bidirectional streaming sessions. Authentication uses the same API key or session cookie as HTTP requests.
Key behaviours:
- WS upgrade validated by `src/lib/ws/handshake.ts` before the connection is established
- Streams terminated cleanly on session close or upstream error
- Works alongside the existing HTTP+SSE streaming path simultaneously
---
## 🔑 Sync Tokens & Config Bundle _(v3.6.6+)_
Multi-device and external operator access is now possible via **scoped sync tokens**:
- **`POST /api/sync/tokens`** — Issue a new sync token (scoped, with optional expiry)
- **`DELETE /api/sync/tokens/:id`** — Revoke a token
- **`GET /api/sync/bundle`** — Download a versioned, ETag-keyed JSON snapshot of all non-sensitive settings (passwords redacted)
The config bundle is built by `src/lib/sync/bundle.ts`. Consumers compare the `ETag` response header to detect changes without re-downloading the full payload.
---
## 🧠 GLM Thinking Preset _(v3.6.6+)_
**GLM Thinking (`glmt`)** is now a registered first-class provider: 65 536 max output tokens, 24 576 thinking budget, 900 s default timeout, Claude-compatible API format, and shared usage sync with the GLM family.
**Hybrid token counting** also lands in v3.6.6: when a Claude-compatible provider exposes `/messages/count_tokens`, OmniRoute calls it before large requests with graceful estimation fallback.
---
## 🛡️ Safe Outbound Fetch & SSRF Guard _(v3.6.6+)_
All provider validation and model discovery calls now go through a two-layer outbound guard:
1. **URL guard** (`src/shared/network/outboundUrlGuard.ts`) — Blocks private/loopback/link-local IP ranges before the socket is opened.
2. **Safe fetch wrapper** (`src/shared/network/safeOutboundFetch.ts`) — Applies the URL guard, normalises timeouts, and retries transient errors with exponential backoff.
Guard violations surface as HTTP 422 (`URL_GUARD_BLOCKED`) and are written to the compliance audit log via `providerAudit.ts`.
---
## 🔄 Cooldown-Aware Retries _(v3.6.6+)_
Chat requests now **automatically retry** when an upstream provider returns a model-scoped cooldown. Configurable via `REQUEST_RETRY` (default: 2) and `MAX_RETRY_INTERVAL_SEC` (default: 30 s). Rate-limit header learning improved across `x-ratelimit-reset-requests`, `x-ratelimit-reset-tokens`, and `Retry-After` — per-model cooldown state is visible in the Resilience dashboard.
---
## 📋 Compliance Audit v2 _(v3.6.6+)_
The audit log has been expanded with cursor-based pagination, request context enrichment (request ID, user agent, IP), structured auth events, provider CRUD events with diff context, and SSRF-blocked validation logging. New events emitted by `src/lib/compliance/providerAudit.ts`.
14'ten fazla yerleşik kodlama CLI aracını tek tıkla yapılandırın, algılayın ve doğrudan OmniRoute'a bağlayın.

View File

@@ -1,441 +1,66 @@
# i18n — Internationalization Guide (Türkçe)
---
title: "i18n — Uluslararasılaşma Kılavuzu"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/I18N.md) · 🇸🇦 [ar](../../ar/docs/I18N.md) · 🇧🇬 [bg](../../bg/docs/I18N.md) · 🇧🇩 [bn](../../bn/docs/I18N.md) · 🇨🇿 [cs](../../cs/docs/I18N.md) · 🇩🇰 [da](../../da/docs/I18N.md) · 🇩🇪 [de](../../de/docs/I18N.md) · 🇪🇸 [es](../../es/docs/I18N.md) · 🇮🇷 [fa](../../fa/docs/I18N.md) · 🇫🇮 [fi](../../fi/docs/I18N.md) · 🇫🇷 [fr](../../fr/docs/I18N.md) · 🇮🇳 [gu](../../gu/docs/I18N.md) · 🇮🇱 [he](../../he/docs/I18N.md) · 🇮🇳 [hi](../../hi/docs/I18N.md) · 🇭🇺 [hu](../../hu/docs/I18N.md) · 🇮🇩 [id](../../id/docs/I18N.md) · 🇮🇹 [it](../../it/docs/I18N.md) · 🇯🇵 [ja](../../ja/docs/I18N.md) · 🇰🇷 [ko](../../ko/docs/I18N.md) · 🇮🇳 [mr](../../mr/docs/I18N.md) · 🇲🇾 [ms](../../ms/docs/I18N.md) · 🇳🇱 [nl](../../nl/docs/I18N.md) · 🇳🇴 [no](../../no/docs/I18N.md) · 🇵🇭 [phi](../../phi/docs/I18N.md) · 🇵🇱 [pl](../../pl/docs/I18N.md) · 🇵🇹 [pt](../../pt/docs/I18N.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/I18N.md) · 🇷🇴 [ro](../../ro/docs/I18N.md) · 🇷🇺 [ru](../../ru/docs/I18N.md) · 🇸🇰 [sk](../../sk/docs/I18N.md) · 🇸🇪 [sv](../../sv/docs/I18N.md) · 🇰🇪 [sw](../../sw/docs/I18N.md) · 🇮🇳 [ta](../../ta/docs/I18N.md) · 🇮🇳 [te](../../te/docs/I18N.md) · 🇹🇭 [th](../../th/docs/I18N.md) · 🇹🇷 [tr](../../tr/docs/I18N.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/I18N.md) · 🇵🇰 [ur](../../ur/docs/I18N.md) · 🇻🇳 [vi](../../vi/docs/I18N.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/I18N.md)
# i18n — Uluslararasılaşma Kılavuzu (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/guides/I18N.md) · 🇸🇦 [ar](../../ar/docs/guides/I18N.md) · 🇧🇬 [bg](../../bg/docs/guides/I18N.md) · 🇧🇩 [bn](../../bn/docs/guides/I18N.md) · 🇨🇿 [cs](../../cs/docs/guides/I18N.md) · 🇩🇰 [da](../../da/docs/guides/I18N.md) · 🇩🇪 [de](../../de/docs/guides/I18N.md) · 🇪🇸 [es](../../es/docs/guides/I18N.md) · 🇮🇷 [fa](../../fa/docs/guides/I18N.md) · 🇫🇮 [fi](../../fi/docs/guides/I18N.md) · 🇫🇷 [fr](../../fr/docs/guides/I18N.md) · 🇮🇳 [gu](../../gu/docs/guides/I18N.md) · 🇮🇱 [he](../../he/docs/guides/I18N.md) · 🇮🇳 [hi](../../hi/docs/guides/I18N.md) · 🇭🇺 [hu](../../hu/docs/guides/I18N.md) · 🇮🇩 [id](../../id/docs/guides/I18N.md) · 🇮🇹 [it](../../it/docs/guides/I18N.md) · 🇯🇵 [ja](../../ja/docs/guides/I18N.md) · 🇰🇷 [ko](../../ko/docs/guides/I18N.md) · 🇮🇳 [mr](../../mr/docs/guides/I18N.md) · 🇲🇾 [ms](../../ms/docs/guides/I18N.md) · 🇳🇱 [nl](../../nl/docs/guides/I18N.md) · 🇳🇴 [no](../../no/docs/guides/I18N.md) · 🇵🇭 [phi](../../phi/docs/guides/I18N.md) · 🇵🇱 [pl](../../pl/docs/guides/I18N.md) · 🇵🇹 [pt](../../pt/docs/guides/I18N.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/guides/I18N.md) · 🇷🇴 [ro](../../ro/docs/guides/I18N.md) · 🇷🇺 [ru](../../ru/docs/guides/I18N.md) · 🇸🇰 [sk](../../sk/docs/guides/I18N.md) · 🇸🇪 [sv](../../sv/docs/guides/I18N.md) · 🇰🇪 [sw](../../sw/docs/guides/I18N.md) · 🇮🇳 [ta](../../ta/docs/guides/I18N.md) · 🇮🇳 [te](../../te/docs/guides/I18N.md) · 🇹🇭 [th](../../th/docs/guides/I18N.md) · 🇹🇷 [tr](../../tr/docs/guides/I18N.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/guides/I18N.md) · 🇵🇰 [ur](../../ur/docs/guides/I18N.md) · 🇻🇳 [vi](../../vi/docs/guides/I18N.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/guides/I18N.md)
---
OmniRoute supports **30 languages** with full dashboard UI translation, translated documentation, and RTL support for Arabic and Hebrew.
OmniRoute, eksiksiz pano kullanıcı arayüzü çevirisi, çevrilmiş dokümantasyon ve Arapça/İbranice için RTL desteği ile **43 dili** destekler.
## Quick Reference
## Çeviri İşlem Hattı (v3.8.0 Önerilen)
| Task | Command |
| ---------------------- | --------------------------------------------------------------------------------------- |
| Generate translations | `node scripts/i18n/generate-multilang.mjs messages` |
| Translate docs (LLM) | `python3 scripts/i18n_autotranslate.py --api-url <url> --api-key <key> --model <model>` |
| Validate a locale | `python3 scripts/validate_translation.py quick -l cs` |
| Check code keys | `python3 scripts/check_translations.py` |
| Generate QA report | `node scripts/i18n/generate-qa-checklist.mjs` |
| Visual QA (Playwright) | `node scripts/i18n/run-visual-qa.mjs` |
OmniRoute, belgeler için OpenAI uyumlu bir LLM uç noktası tarafından desteklenen karma (hash) tabanlı artımlı bir çevirmen kullanır:
```bash
# Çevirileri çalıştır (artımlı — yalnızca değişen kaynaklara dokunur)
npm run i18n:run
# Tek bir yerel ayarla sınırla
npm run i18n:run -- --locale=tr
# Belirli dosyaları çevir (virgülle ayrılmış, depoya göreli yollar)
npm run i18n:run -- --files=CLAUDE.md,docs/architecture/ARCHITECTURE.md
# Önizleme (API çağrısı veya yazma yapmaz)
npm run i18n:run:dry
# CI kalite kapısı — çeviri sapması varsa sıfır olmayan kodla çıkar
npm run i18n:check
```
**Doğruluk Kaynağı:** `config/i18n.json` tüm yerel ayarları (UI + belgeler), RTL kümesini ve `docsExcluded` kodlarını listeler. `src/i18n/config.ts` içindeki çalışma zamanı yapılandırması bu JSON üzerinde ince bir bağdaştırıcıdır.
---
## Hızlı Başvuru
| Görev | Komut |
| -------------------------- | ---------------------------------------------------------- |
| Belgeleri Çevirme (LLM) | `npm run i18n:run` (tercih edilen — artımlı, hash tabanlı) |
| UI Dizelerini Çevirme | `node scripts/i18n/generate-multilang.mjs messages` |
| Çeviri Sapmasını Kontrol Et| `npm run i18n:check` |
| Bir Dili Doğrulama | `python3 scripts/i18n/validate_translation.py quick -l tr` |
| Kod Anahtarlarını Kontrol | `python3 scripts/i18n/check_translations.py` |
| Kalite Raporu Üretme | `node scripts/i18n/generate-qa-checklist.mjs` |
| Görsel Kalite (Playwright) | `node scripts/i18n/run-visual-qa.mjs` |
---
## Mimari
### Source of Truth
- **UI Dizeleri**: `src/i18n/messages/en.json` (İngilizce kaynak, ~2800 anahtar)
- **Yerel Ayar Dosyaları**: `src/i18n/messages/{locale}.json` (43 çeviri)
- **Framework**: Çerez tabanlı yerel ayar çözümlemesi ile `next-intl`
- **Yapılandırma**: `src/i18n/config.ts` — tüm 43 yerel ayarı, dil adlarını ve bayrakları tanımlar
- **UI strings**: `src/i18n/messages/en.json` (English source, ~2800 keys)
- **Locale files**: `src/i18n/messages/{locale}.json` (30 translations)
- **Framework**: `next-intl` with cookie-based locale resolution
- **Config**: `src/i18n/config.ts` — defines all 30 locales, language names, flags
### Çalışma Zamanı Akışı
### Runtime Flow
1. User selects language → `NEXT_LOCALE` cookie set
2. `src/i18n/request.ts` resolves locale: cookie → `Accept-Language` header → fallback `en`
3. Dynamic import loads `messages/{locale}.json`
4. Components use `useTranslations("namespace")` and `t("key")`
### Supported Locales
| Code | Language | RTL | Google Translate Code |
| ------- | -------------------- | --- | --------------------- |
| `ar` | العربية | Yes | `ar` |
| `bg` | Български | No | `bg` |
| `cs` | Čeština | No | `cs` |
| `da` | Dansk | No | `da` |
| `de` | Deutsch | No | `de` |
| `es` | Español | No | `es` |
| `fi` | Suomi | No | `fi` |
| `fr` | Français | No | `fr` |
| `he` | עברית | Yes | `iw` |
| `hi` | हिन्दी | No | `hi` |
| `hu` | Magyar | No | `hu` |
| `id` | Bahasa Indonesia | No | `id` |
| `it` | Italiano | No | `it` |
| `ja` | 日本語 | No | `ja` |
| `ko` | 한국어 | No | `ko` |
| `ms` | Bahasa Melayu | No | `ms` |
| `nl` | Nederlands | No | `nl` |
| `no` | Norsk | No | `no` |
| `phi` | Filipino | No | `tl` |
| `pl` | Polski | No | `pl` |
| `pt` | Português (Portugal) | No | `pt` |
| `pt-BR` | Português (Brasil) | No | `pt` |
| `ro` | Română | No | `ro` |
| `ru` | Русский | No | `ru` |
| `sk` | Slovenčina | No | `sk` |
| `sv` | Svenska | No | `sv` |
| `th` | ไทย | No | `th` |
| `tr` | Türkçe | No | `tr` |
| `uk-UA` | Українська | No | `uk` |
| `vi` | Tiếng Việt | No | `vi` |
| `zh-CN` | 中文 (简体) | No | `zh-CN` |
## Adding a New Language
### 1. Register the Locale
Edit `src/i18n/config.ts`:
```ts
// Add to LOCALES array
"xx",
// Add to LANGUAGES array
{ code: "xx", label: "XX", name: "Language Name", flag: "🏳️" },
```
### 2. Add to Generator
Edit `scripts/i18n/generate-multilang.mjs` — add entry to `LOCALE_SPECS`:
```js
{
code: "xx",
googleTl: "xx",
label: "XX",
flag: "🏳️",
languageName: "Language Name",
readmeName: "Language Name",
docsName: "Language Name",
},
```
### 3. Generate Initial Translation
```bash
node scripts/i18n/generate-multilang.mjs messages
```
This creates `src/i18n/messages/xx.json` auto-translated from `en.json` via Google Translate.
### 4. Review & Fix Auto-Translations
Auto-translations are a starting point. Review manually for:
- Technical accuracy
- Context-appropriate terminology
- Proper handling of placeholders (`{count}`, `{value}`, etc.)
### 5. Validate
```bash
python3 scripts/validate_translation.py quick -l xx
python3 scripts/validate_translation.py diff common -l xx
```
### 6. Generate Translated Documentation
```bash
node scripts/i18n/generate-multilang.mjs docs
```
## Auto-Translation Pipeline
### generate-multilang.mjs (Google Translate)
**Primary auto-translation engine** — uses Google Translate free API to generate translations for UI strings, READMEs, and documentation.
```bash
node scripts/i18n/generate-multilang.mjs [messages|readme|docs|all]
```
| Mode | What it does |
| ---------- | ----------------------------------------------------------------------------- |
| `messages` | Translates missing keys in `src/i18n/messages/{locale}.json` from `en.json` |
| `readme` | Translates `README.md` into all locales as `README.{code}.md` in project root |
| `docs` | Translates `DOC_SOURCE_FILES` into `docs/i18n/{locale}/{docName}` |
| `all` | Runs all three modes |
**Features:**
- **Text protection**: Masks code blocks (` ``` `), inline code (`` ` ``), markdown links/images (`[text](url)`), HTML tags, tables, and ICU placeholders (`{count}`, `{value}`, `{total}`, etc.) before translation, then restores them
- **Chunked batching**: Joins multiple strings with `__OMNIROUTE_I18N_SEPARATOR__` delimiters to minimize API calls (max 1800 chars per request)
- **In-memory cache**: Avoids redundant API calls for repeated strings within a session
- **Retry logic**: Exponential backoff (up to 5 attempts with 300ms × attempt delay) for 429/5xx errors
- **Timeout**: 20 seconds per request
- **Skip existing**: If target file already exists, it is NOT overwritten
**Important behaviors:**
- `docs/i18n/README.md` is **regenerated** each run — it's an auto-generated index of all docs
- Root `README.{code}.md` files are only created if they don't exist (skips locales in `EXISTING_README_CODES`)
- Language bars (`🌐 **Languages:** ...`) are automatically inserted/updated in all translated docs
### i18n_autotranslate.py (LLM-based)
**Secondary translator** — uses any OpenAI-compatible LLM API (including OmniRoute itself) to translate existing `docs/i18n/` markdown files. Best for polishing or re-translating docs with better quality than Google Translate.
```bash
python3 scripts/i18n_autotranslate.py \
--api-url http://localhost:20128/v1 \
--api-key sk-your-key \
--model gpt-4o
```
**Features:**
- Scans `docs/i18n/` markdown files for English paragraphs
- Skips code blocks, tables, and already-translated content
- Sends paragraphs to LLM with technical translation system prompt
- Supports all 30 languages
## Validation & QA
### validate_translation.py
**Translation validator** — compares any locale JSON against `en.json` and reports issues.
```bash
# Quick check (counts only)
python3 scripts/validate_translation.py quick -l cs
# Output:
# Missing: 0
# Untranslated: 0
# Ignored (UNTRANSLATABLE_KEYS): 236
# Detailed diff by category
python3 scripts/validate_translation.py diff common -l cs
python3 scripts/validate_translation.py diff settings -l cs
# Export to CSV
python3 scripts/validate_translation.py csv -l cs > report.csv
# Export to Markdown
python3 scripts/validate_translation.py md -l cs > report.md
# Full report (default)
python3 scripts/validate_translation.py -l cs
```
**Detects:**
- **Missing keys** — keys in `en.json` but not in locale file
- **Extra keys** — keys in locale file but not in `en.json`
- **Untranslated keys** — keys where locale value equals English source (excluding allowlist)
- **Placeholder mismatches** — ICU placeholders that don't match between source and translation
**Exit codes:**
| Code | Meaning |
|------|---------|
| 0 | OK |
| 1 | Generic error |
| 2 | Missing strings (hard error) |
| 3 | Untranslated warning (soft) |
**Environment:** Set `TRANSLATION_LANG=cs` or use `-l cs` flag.
### check_translations.py
**Code-to-JSON key checker** — scans `src/**/*.tsx` and `src/**/*.ts` for `useTranslations()` calls and verifies all referenced keys exist in `en.json`.
```bash
# Basic check
python3 scripts/check_translations.py
# Verbose output
python3 scripts/check_translations.py --verbose
# Auto-fix (adds missing keys to en.json)
python3 scripts/check_translations.py --fix
```
### generate-qa-checklist.mjs
**Static analysis QA** — scans Next.js page files for i18n risk metrics and generates a Markdown report.
```bash
node scripts/i18n/generate-qa-checklist.mjs
```
**Checks:**
- Fixed-width class usage (overflow risk)
- Directional left/right classes (RTL risk)
- Clipping-prone patterns
- Locale parity (missing/extra keys vs `en.json`)
- README language selector bars in priority locales (`es`, `fr`, `de`, `ja`, `ar`)
**Output:** `docs/reports/i18n-qa-checklist-{date}.md`
### run-visual-qa.mjs
**Visual QA via Playwright** — takes screenshots of all dashboard routes in multiple locales and viewports, then evaluates page health.
```bash
# Default: es, fr, de, ja, ar on localhost:20128
node scripts/i18n/run-visual-qa.mjs
# Custom base URL and locales
QA_BASE_URL=http://staging.example.com QA_LOCALES=de,fr node scripts/i18n/run-visual-qa.mjs
# Custom routes
QA_ROUTES=/dashboard/settings,/dashboard/providers node scripts/i18n/run-visual-qa.mjs
```
**Detects:**
- Text overflow
- Element clipping
- RTL layout mismatches
**Output:** `docs/reports/i18n-visual-qa-{date}.md` + JSON report
## Managing Untranslatable Keys
### untranslatable-keys.json
**File:** `scripts/i18n/untranslatable-keys.json`
Allowlist of keys that should remain identical to English source. Used by `validate_translation.py` to avoid false-positive "untranslated" warnings.
```json
{
"description": "Keys that should remain untranslated...",
"keys": [
"common.model",
"common.oauth",
"health.cpu",
...
]
}
```
**What belongs here:**
- Brand/product names: `landing.brandName`, `common.social-github`
- Technical terms/acronyms: `health.cpu`, `mcpDashboard.pid`, `settings.ai`
- ICU/format strings: `apiManager.modelsCount`, `health.millisecondsShort`
- Placeholder values: `providers.openaiBaseUrlPlaceholder`, `cliTools.baseUrlPlaceholder`
- Protocol names: `common.http`, `common.oauth`, `providers.oauth2Label`
- Navigation sections: `sidebar.primarySection`, `sidebar.cliSection`
**To add a key:** Edit the `keys` array in `scripts/i18n/untranslatable-keys.json` and re-run validation.
## CI Integration
### GitHub Actions (`.github/workflows/ci.yml`)
The CI pipeline validates all locales on every push and PR:
1. **`i18n-matrix` job** — dynamically discovers all locale files (excluding `en.json`)
2. **`i18n` job** — runs `validate_translation.py quick -l '<lang>'` for each locale in parallel
3. **`ci-summary` job** — aggregates results into a dashboard summary
```yaml
# i18n-matrix: discovers languages
LANGS=$(ls src/i18n/messages/*.json | xargs -n1 basename | sed 's/.json$//' | grep -v '^en$')
# i18n: validates each language
python3 scripts/validate_translation.py quick -l '${{ matrix.lang }}'
```
**Dashboard output:**
```
## 🌍 Translations
| Metric | Value |
|--------|------|
| Languages checked | 30 |
| Total untranslated | 0 |
✅ All translations complete
```
## File Structure
```
src/i18n/
├── config.ts # Locale definitions (30 locales, RTL config)
├── request.ts # Runtime locale resolution
└── messages/
├── en.json # Source of truth (~2800 keys)
├── cs.json # Czech translation
├── de.json # German translation
└── ... # 30 locale files total
scripts/
├── i18n/
│ ├── generate-multilang.mjs # Auto-translation engine (Google Translate, 888 lines)
│ ├── generate-qa-checklist.mjs # Static analysis QA
│ ├── run-visual-qa.mjs # Playwright visual QA
│ └── untranslatable-keys.json # Allowlist for validation (236 keys)
├── validate_translation.py # Translation validator
├── check_translations.py # Code-to-JSON key checker
└── i18n_autotranslate.py # LLM-based doc translator
.github/workflows/
└── ci.yml # i18n validation in CI matrix
docs/
├── I18N.md # This file — i18n toolchain documentation
├── i18n/
│ ├── README.md # Auto-generated language index
│ ├── cs/ # Czech docs
│ │ └── docs/
│ │ ├── I18N.md # Czech translation of this file
│ │ └── ...
│ ├── de/ # German docs
│ └── ... # 30 locale directories
└── reports/
├── i18n-qa-checklist-*.md # Static analysis reports
└── i18n-visual-qa-*.md # Visual QA reports
```
## Best Practices
### When Editing Translations
1. **Always edit `en.json` first** — it's the source of truth
2. **Run `generate-multilang.mjs messages`** to propagate new keys to all locales
3. **Review auto-translations** — Google Translate is a starting point, not final
4. **Validate before committing**`python3 scripts/validate_translation.py quick -l <lang>`
5. **Update `untranslatable-keys.json`** if a key should remain in English
### Placeholder Safety
- ICU placeholders (`{count}`, `{value}`, `{total}`, `{seconds}`) must be preserved exactly
- Plural formats (`{count, plural, one {# model} other {# models}}`) must maintain structure
- The validator detects placeholder mismatches automatically
### Adding New Translation Keys in Code
```tsx
// Use namespaced keys
const t = useTranslations("settings");
t("cacheSettings"); // maps to settings.cacheSettings in JSON
// Run check_translations.py to verify keys exist
python3 scripts/check_translations.py --verbose
```
### RTL Considerations
- Arabic (`ar`) and Hebrew (`he`) are RTL locales
- Avoid hardcoded `left`/`right` CSS — use `start`/`end` logical properties
- Visual QA catches RTL layout mismatches via `run-visual-qa.mjs`
## Known Issues & History
### `in.json` → `hi.json` Fix
The generator originally used `code: "in"` (deprecated Google Translate code) for Hindi instead of the correct ISO 639-1 `hi`. This created an orphaned `in.json` duplicate of `hi.json`. Fixed by changing `code: "in"` to `code: "hi"` in `generate-multilang.mjs` and removing the orphaned file.
### `docs/i18n/README.md` Is Auto-Generated
The `docs/i18n/README.md` file is completely regenerated by `generate-multilang.mjs docs`. Any manual edits will be lost. Use `docs/guides/I18N.md` (this file) for hand-written documentation that should persist.
### External Untranslatable Keys List
The `untranslatable-keys.json` allowlist was moved from an inline Python set in `validate_translation.py` to an external JSON file for easier maintenance. The validator loads it at runtime.
### `generate-multilang.mjs` Hindi Code Fix
The generator originally used `code: "in"` (deprecated Google Translate code) for Hindi instead of the correct ISO 639-1 `hi`. This was introduced in upstream commit `952b0b22c` by `diegosouzapw`. Fixed by changing `code: "in"` to `code: "hi"` in the `LOCALE_SPECS` array and removing the orphaned `in.json` file.
### `validate_translation.py` Ignored Count Output
The `quick` check now displays the count of ignored keys from `untranslatable-keys.json`:
```
Missing: 0
Untranslated: 0
Ignored (UNTRANSLATABLE_KEYS): 236
```
1. Kullanıcı dili seçer → `NEXT_LOCALE` çerezi ayarlanır
2. `src/i18n/request.ts` yerel ayarı çözer: çerez → `Accept-Language` başlığı → geri dönüş `en`
3. Dinamik içe aktarma `messages/{locale}.json` dosyasını yükler
4. Bileşenler `useTranslations("namespace")` ve `t("key")` kullanır

View File

@@ -1,340 +1,48 @@
# Troubleshooting (Türkçe)
---
title: "Sorun Giderme"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇧🇩 [bn](../../bn/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇮🇷 [fa](../../fa/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇮🇳 [gu](../../gu/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇮🇳 [hi](../../hi/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇮🇳 [mr](../../mr/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇰🇪 [sw](../../sw/docs/TROUBLESHOOTING.md) · 🇮🇳 [ta](../../ta/docs/TROUBLESHOOTING.md) · 🇮🇳 [te](../../te/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇹🇷 [tr](../../tr/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇵🇰 [ur](../../ur/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md)
# Sorun Giderme (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/guides/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/guides/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/guides/TROUBLESHOOTING.md) · 🇧🇩 [bn](../../bn/docs/guides/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/guides/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/guides/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/guides/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/guides/TROUBLESHOOTING.md) · 🇮🇷 [fa](../../fa/docs/guides/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/guides/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/guides/TROUBLESHOOTING.md) · 🇮🇳 [gu](../../gu/docs/guides/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/guides/TROUBLESHOOTING.md) · 🇮🇳 [hi](../../hi/docs/guides/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/guides/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/guides/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/guides/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/guides/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/guides/TROUBLESHOOTING.md) · 🇮🇳 [mr](../../mr/docs/guides/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/guides/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/guides/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/guides/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/guides/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/guides/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/guides/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/guides/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/guides/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/guides/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/guides/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/guides/TROUBLESHOOTING.md) · 🇰🇪 [sw](../../sw/docs/guides/TROUBLESHOOTING.md) · 🇮🇳 [ta](../../ta/docs/guides/TROUBLESHOOTING.md) · 🇮🇳 [te](../../te/docs/guides/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/guides/TROUBLESHOOTING.md) · 🇹🇷 [tr](../../tr/docs/guides/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/guides/TROUBLESHOOTING.md) · 🇵🇰 [ur](../../ur/docs/guides/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/guides/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/guides/TROUBLESHOOTING.md)
---
Common problems and solutions for OmniRoute.
OmniRoute için sık karşılaşılan sorunlar ve çözümleri.
---
## Quick Fixes
## Hızlı Başvuru
| 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 | Check Node.js version — see [Node.js Compatibility](#nodejs-compatibility) below |
| `dlopen` / `slice is not valid mach-o file` (macOS) | Run `cd $(npm root -g)/omniroute/app && npm rebuild better-sqlite3 && omniroute` — see [macOS native module rebuild](#macos-native-module-rebuild) below |
| Proxy "fetch failed" | Ensure proxy config is set at the correct level — see [Proxy Issues](#proxy-issues) below |
**OmniRoute'ta yeni misiniz?** Buradan başlayın — sorunların %90'ını çözer:
| Gördüğüm Durum | Ne Anlama Geliyor | Ne Yapılmalı |
| ------------------------ | ----------------------------------- | ------------------------------------------------------------------------------------------------- |
| "Bağlanamıyor" | OmniRoute çalışmıyor | `omniroute` veya `docker restart omniroute` çalıştırın |
| "Geçersiz API Anahtarı" | Anahtarınız yanlış veya süresi doldu| Sağlayıcının web sitesinden anahtarı yeniden kopyalayın |
| "Hız Sınırııldı" | Çok fazla istek gönderiyorsunuz | 1 dakika bekleyin veya otomatik geri dönüş için `model: "auto"` kullanın |
| "Kota Aşıldı" | Ücretsiz/ücretli kotanız bitti | Daha fazla sağlayıcı bağlayın veya ücretsiz sağlayıcıları kullanın |
| "Yavaş Yanıtlar" | Sağlayıcı meşgul veya uzakta | `model: "auto/fast"` kullanın veya daha hızlı bir sağlayıcı bağlayın (Groq, Cerebras) |
| "Yanlış Sağlayıcı Seçimi"| `auto` farklı bir sağlayıcı seçti | Bu normaldir! `auto` en iyisini seçer. Belirli bir sağlayıcıyı `model: "openai/gpt-4o"` ile zorlayın |
| "502 Bad Gateway" | Sağlayıcı çöktü | Bekleyip yeniden deneyin veya sağlayıcı değiştirmek için `model: "auto"` kullanın |
| "401 Unauthorized" | Kimlik bilgileriniz geçersiz | API anahtarınızı kontrol edin veya OAuth ile yeniden doğrulayın |
| "429 Too Many Requests" | Hız sınırına takıldı | 1 dakika bekleyin veya daha fazla sağlayıcı bağlayın |
---
## Node.js Compatibility
<a name="nodejs-compatibility"></a>
### Login page crashes or shows "Module self-registration" error
**Cause:** You are running a Node.js version outside OmniRoute's approved secure runtime floor. The most common case is running an older Node 20, 22, or 24 patch level that falls below the patched security floor OmniRoute requires.
**Symptoms:**
- Login page shows a blank screen or a server error
- Console shows `Error: Module did not self-register` or similar native binding errors
- The login page shows an **orange warning banner** with your Node version if the runtime is outside the supported secure policy
**Fix:**
1. Install a supported Node.js LTS release (recommended: Node.js 24.x):
```bash
nvm install 24
nvm use 24
```
2. Verify your version: `node --version` should show `v24.0.0` or newer on the 24.x LTS line
3. Reinstall OmniRoute: `npm install -g omniroute`
4. Restart: `omniroute`
> **Supported secure versions:** `>=20.20.2 <21`, `>=22.22.2 <23`, or `>=24.0.0 <25`. Node.js 24.x LTS (Krypton) is fully supported.
### macOS: `dlopen` / "slice is not valid mach-o file"
<a name="macos-native-module-rebuild"></a>
**Cause:** After a global `npm install -g omniroute`, the `better-sqlite3` native binary inside the package may have been compiled for a different architecture or Node.js ABI than what is running locally. This is common on macOS (both Apple Silicon and Intel) when the pre-built binary does not match your environment.
**Symptoms:**
- Server fails immediately on startup with a `dlopen` error
- Error contains `slice is not valid mach-o file`
- Full example:
```
dlopen(/Users/<user>/.nvm/versions/node/v24.14.1/lib/node_modules/omniroute/app/node_modules/better-sqlite3/build/Release/better_sqlite3.node, 0x0001): tried: '...' (slice is not valid mach-o file)
```
**Fix — rebuild for your local environment (no Node.js downgrade required):**
```bash
cd $(npm root -g)/omniroute/app
npm rebuild better-sqlite3
omniroute
```
> **Note:** This recompiles the native binding against your local Node.js version and CPU architecture, resolving the binary mismatch. The officially supported range is **`>=20.20.2 <21`, `>=22.22.2 <23`, or `>=24.0.0 <25`** (`engines` field in `package.json`). Node.js 24.x LTS (Krypton) is fully supported with `better-sqlite3` v12.x.
---
## Proxy Issues
<a name="proxy-issues"></a>
### Provider validation shows "fetch failed"
**Cause:** The API key validation endpoint (`POST /api/providers/validate`) was previously bypassing proxy configuration, causing failures in environments that require proxy routing.
**Fix (v3.5.5+):** This is now fixed. Provider validation routes through `runWithProxyContext`, honoring provider-level and global proxy settings automatically.
### Token health check fails with "fetch failed"
**Cause:** Background OAuth token refresh was not resolving proxy configuration per connection.
**Fix (v3.5.5+):** The token health check scheduler now resolves proxy config per connection before attempting refresh. Update to v3.5.5+.
### SOCKS5 proxy returns "invalid onRequestStart method"
**Cause:** On Node.js 22, the undici@8 dispatcher is incompatible with Node's built-in `fetch()` implementation.
**Fix (v3.5.5+):** OmniRoute now uses undici's own `fetch()` function when a proxy dispatcher is active, ensuring consistent behavior. Update to v3.5.5+.
---
## Provider Issues
### "Language model did not provide messages"
**Cause:** Provider quota exhausted.
**Fix:**
1. Check dashboard quota tracker
2. Use a combo with fallback tiers
3. Switch to cheaper/free tier
### Rate Limiting
**Cause:** Subscription quota exhausted.
**Fix:**
- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
- Use GLM/MiniMax as cheap backup
### OAuth Token Expired
OmniRoute auto-refreshes tokens. If issues persist:
1. Dashboard → Provider → Reconnect
2. Delete and re-add the provider connection
---
## Cloud Issues
### Cloud Sync Errors
1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
### Cloud `stream=false` Returns 500
**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
**Cause:** Upstream returns SSE payload while client expects JSON.
**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
### Cloud Says Connected but "Invalid API key"
1. Create a fresh key from local dashboard (`/api/keys`)
2. Run cloud sync: Enable Cloud → Sync Now
3. Old/non-synced keys can still return `401` on cloud
---
## Docker Issues
### CLI Tool Shows Not Installed
1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
2. For portable mode: use image target `runner-cli` (bundled CLIs)
3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
### Quick Runtime Validation
```bash
curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
```
---
## Cost Issues
### High Costs
1. Check usage stats in Dashboard → Usage
2. Switch primary model to GLM/MiniMax
3. Set cost budgets per API key: Dashboard → API Keys → Budget
---
## Debugging
### Enable Log Files
Set `APP_LOG_TO_FILE=true` in your `.env` file. Application logs are written under `logs/`.
Request artifacts are stored under `${DATA_DIR}/call_logs/` when the call log pipeline is
enabled in settings.
### Check Provider Health
```bash
# Health dashboard
http://localhost:20128/dashboard/health
# API health check
curl http://localhost:20128/api/monitoring/health
```
### Runtime Storage
- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/call_logs/`
- Application logs: `<repo>/logs/...` (when `APP_LOG_TO_FILE=true`)
- Call log artifacts: `${DATA_DIR}/call_logs/YYYY-MM-DD/...` when the call log pipeline is enabled
---
## Circuit Breaker Issues
### Provider stuck in OPEN state
When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
**Fix:**
1. Go to **Dashboard → Settings → Resilience**
2. Check the circuit breaker card for the affected provider
3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
4. Verify the provider is actually available before resetting
### Provider keeps tripping the circuit breaker
If a provider repeatedly enters OPEN state:
1. Check **Dashboard → Health → Provider Health** for the failure pattern
2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
3. Check if the provider has changed API limits or requires re-authentication
4. Review latency telemetry — high latency may cause timeout-based failures
---
## Audio Transcription Issues
### "Unsupported model" error
- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
- Verify the provider is connected in **Dashboard → Providers**
### Transcription returns empty or fails
- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
- Verify file size is within provider limits (typically < 25MB)
- Check provider API key validity in the provider card
---
## Translator Debugging
Use **Dashboard → Translator** to debug format translation issues:
| Mode | When to Use |
| ---------------- | -------------------------------------------------------------------------------------------- |
| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
### Common format issues
- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
---
## Resilience Settings
### Auto rate-limit not triggering
- Auto rate-limit only applies to API key providers (not OAuth/subscription)
- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
- Check if the provider returns `429` status codes or `Retry-After` headers
### Tuning exponential backoff
Provider profiles support these settings:
- **Base delay** — Initial wait time after first failure (default: 1s)
- **Max delay** — Maximum wait time cap (default: 30s)
- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
### Anti-thundering herd
When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
---
## Optional RAG / LLM failure taxonomy (16 problems)
Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
- retrieval drift and broken context boundaries
- empty or stale indexes and vector stores
- embedding versus semantic mismatch
- prompt assembly and context window issues
- logic collapse and overconfident answers
- long chain and agent coordination failures
- multi agent memory and role drift
- deployment and bootstrap ordering problems
The idea is simple:
1. When you investigate a bad response, capture:
- user task and request
- route or provider combo in OmniRoute
- any RAG context used downstream (retrieved documents, tool calls, etc)
2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
Full text and concrete recipes live here (MIT license, text only):
[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
---
## Still Stuck?
- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **Architecture**: See [`docs/architecture/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
- **API Reference**: See [`docs/reference/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
- **Translator**: Use **Dashboard → Translator** to debug format issues
## Hızlı Düzeltmeler
| Sorun | Çözüm |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| İlk giriş çalışmıyor | `.env` dosyasında `INITIAL_PASSWORD` ayarlayın (sabit kodlanmış varsayılan yoktur) |
| Pano yanlış portta açılıyor | `PORT=20128` ve `NEXT_PUBLIC_BASE_URL=http://localhost:20128` ayarlayın |
| Diske günlük yazılmıyor | `APP_LOG_TO_FILE=true` ayarlayın ve çağrı günlüğü kaydının etkin olduğunu doğrulayın |
| EACCES: permission denied | `~/.omniroute` dizinini geçersiz kılmak için `DATA_DIR=/yazilabilir/dizin/yolu` ayarlayın |
| Yönlendirme stratejisi kaydedilmiyor | En son v3.x sürümüne güncelleyin |
| Giriş çökmesi / boş sayfa | Node.js sürümünü kontrol edin (Node.js `>=22.22.2 <23` veya `>=24.0.0 <27` desteklenir) |
| `dlopen` / `slice is not valid mach-o file` (macOS) | `cd $(npm root -g)/omniroute/app && npm rebuild better-sqlite3 && omniroute` çalıştırın |
| Proxy "fetch failed" | Proxy yapılandırmasının doğru düzeyde ayarlandığından emin olun |
| Docker `curl: (56) Recv failure: Connection reset by peer` | Docker port bağlamanız IPv6'ya düşüyor olabilir. IPv4'ü zorlamak için `-p 127.0.0.1:20128:20128` kullanın veya `curl -4` ile test edin |
| Antivirüs `README.md` dosyasını karantinaya alıyor | Yanlış pozitif (false positive) alarmdır, güvenle geri yükleyebilirsiniz |

View File

@@ -1,157 +1,94 @@
# OmniRoute — Uninstall Guide (Türkçe)
---
title: "OmniRoute — Kaldırma Kılavuzu"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/UNINSTALL.md) · 🇸🇦 [ar](../../ar/docs/UNINSTALL.md) · 🇧🇬 [bg](../../bg/docs/UNINSTALL.md) · 🇧🇩 [bn](../../bn/docs/UNINSTALL.md) · 🇨🇿 [cs](../../cs/docs/UNINSTALL.md) · 🇩🇰 [da](../../da/docs/UNINSTALL.md) · 🇩🇪 [de](../../de/docs/UNINSTALL.md) · 🇪🇸 [es](../../es/docs/UNINSTALL.md) · 🇮🇷 [fa](../../fa/docs/UNINSTALL.md) · 🇫🇮 [fi](../../fi/docs/UNINSTALL.md) · 🇫🇷 [fr](../../fr/docs/UNINSTALL.md) · 🇮🇳 [gu](../../gu/docs/UNINSTALL.md) · 🇮🇱 [he](../../he/docs/UNINSTALL.md) · 🇮🇳 [hi](../../hi/docs/UNINSTALL.md) · 🇭🇺 [hu](../../hu/docs/UNINSTALL.md) · 🇮🇩 [id](../../id/docs/UNINSTALL.md) · 🇮🇹 [it](../../it/docs/UNINSTALL.md) · 🇯🇵 [ja](../../ja/docs/UNINSTALL.md) · 🇰🇷 [ko](../../ko/docs/UNINSTALL.md) · 🇮🇳 [mr](../../mr/docs/UNINSTALL.md) · 🇲🇾 [ms](../../ms/docs/UNINSTALL.md) · 🇳🇱 [nl](../../nl/docs/UNINSTALL.md) · 🇳🇴 [no](../../no/docs/UNINSTALL.md) · 🇵🇭 [phi](../../phi/docs/UNINSTALL.md) · 🇵🇱 [pl](../../pl/docs/UNINSTALL.md) · 🇵🇹 [pt](../../pt/docs/UNINSTALL.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/UNINSTALL.md) · 🇷🇴 [ro](../../ro/docs/UNINSTALL.md) · 🇷🇺 [ru](../../ru/docs/UNINSTALL.md) · 🇸🇰 [sk](../../sk/docs/UNINSTALL.md) · 🇸🇪 [sv](../../sv/docs/UNINSTALL.md) · 🇰🇪 [sw](../../sw/docs/UNINSTALL.md) · 🇮🇳 [ta](../../ta/docs/UNINSTALL.md) · 🇮🇳 [te](../../te/docs/UNINSTALL.md) · 🇹🇭 [th](../../th/docs/UNINSTALL.md) · 🇹🇷 [tr](../../tr/docs/UNINSTALL.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/UNINSTALL.md) · 🇵🇰 [ur](../../ur/docs/UNINSTALL.md) · 🇻🇳 [vi](../../vi/docs/UNINSTALL.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/UNINSTALL.md)
# OmniRoute — Kaldırma Kılavuzu (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/guides/UNINSTALL.md) · 🇸🇦 [ar](../../ar/docs/guides/UNINSTALL.md) · 🇧🇬 [bg](../../bg/docs/guides/UNINSTALL.md) · 🇧🇩 [bn](../../bn/docs/guides/UNINSTALL.md) · 🇨🇿 [cs](../../cs/docs/guides/UNINSTALL.md) · 🇩🇰 [da](../../da/docs/guides/UNINSTALL.md) · 🇩🇪 [de](../../de/docs/guides/UNINSTALL.md) · 🇪🇸 [es](../../es/docs/guides/UNINSTALL.md) · 🇮🇷 [fa](../../fa/docs/guides/UNINSTALL.md) · 🇫🇮 [fi](../../fi/docs/guides/UNINSTALL.md) · 🇫🇷 [fr](../../fr/docs/guides/UNINSTALL.md) · 🇮🇳 [gu](../../gu/docs/guides/UNINSTALL.md) · 🇮🇱 [he](../../he/docs/guides/UNINSTALL.md) · 🇮🇳 [hi](../../hi/docs/guides/UNINSTALL.md) · 🇭🇺 [hu](../../hu/docs/guides/UNINSTALL.md) · 🇮🇩 [id](../../id/docs/guides/UNINSTALL.md) · 🇮🇹 [it](../../it/docs/guides/UNINSTALL.md) · 🇯🇵 [ja](../../ja/docs/guides/UNINSTALL.md) · 🇰🇷 [ko](../../ko/docs/guides/UNINSTALL.md) · 🇮🇳 [mr](../../mr/docs/guides/UNINSTALL.md) · 🇲🇾 [ms](../../ms/docs/guides/UNINSTALL.md) · 🇳🇱 [nl](../../nl/docs/guides/UNINSTALL.md) · 🇳🇴 [no](../../no/docs/guides/UNINSTALL.md) · 🇵🇭 [phi](../../phi/docs/guides/UNINSTALL.md) · 🇵🇱 [pl](../../pl/docs/guides/UNINSTALL.md) · 🇵🇹 [pt](../../pt/docs/guides/UNINSTALL.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/guides/UNINSTALL.md) · 🇷🇴 [ro](../../ro/docs/guides/UNINSTALL.md) · 🇷🇺 [ru](../../ru/docs/guides/UNINSTALL.md) · 🇸🇰 [sk](../../sk/docs/guides/UNINSTALL.md) · 🇸🇪 [sv](../../sv/docs/guides/UNINSTALL.md) · 🇰🇪 [sw](../../sw/docs/guides/UNINSTALL.md) · 🇮🇳 [ta](../../ta/docs/guides/I18N.md) · 🇮🇳 [te](../../te/docs/guides/UNINSTALL.md) · 🇹🇭 [th](../../th/docs/guides/UNINSTALL.md) · 🇹🇷 [tr](../../tr/docs/guides/UNINSTALL.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/guides/UNINSTALL.md) · 🇵🇰 [ur](../../ur/docs/guides/UNINSTALL.md) · 🇻🇳 [vi](../../vi/docs/guides/UNINSTALL.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/guides/UNINSTALL.md)
---
This guide covers how to cleanly remove OmniRoute from your system.
Bu kılavuz, OmniRoute'u sisteminizden nasıl temiz bir şekilde kaldıracağınızı kapsar.
---
## Quick Uninstall (v3.6.2+)
## Hızlı Kaldırma (v3.6.2+)
OmniRoute provides two built-in scripts for clean removal:
OmniRoute temiz kaldırma için iki yerleşik betik sunar:
### Keep Your Data
### Verilerinizi Koruyarak Kaldırma
```bash
npm run uninstall
```
This removes the OmniRoute application but **preserves** your database, configurations, API keys, and provider settings in `~/.omniroute/`. Use this if you plan to reinstall later and want to keep your setup.
Bu, OmniRoute uygulamasını kaldırır ancak `~/.omniroute/` içindeki veritabanınızı, yapılandırmalarınızı, API anahtarlarınızı ve sağlayıcı ayarlarınızı **korur**. Daha sonra yeniden yüklemeyi planlıyorsanız ve kurulumunuzu saklamak istiyorsanız bunu kullanın.
### Full Removal
### Tam Kaldırma (Tüm Verileri Sil)
```bash
npm run uninstall:full
```
This removes the application **and permanently erases** all data:
Bu, uygulamayı kaldırır **ve tüm verileri kalıcı olarak siler**:
- Database (`storage.sqlite`)
- Provider configurations and API keys
- Backup files
- Log files
- All files in the `~/.omniroute/` directory
- Veritabanı (`storage.sqlite`)
- Sağlayıcı yapılandırmaları ve API anahtarları
- Yedekleme dosyaları
- Günlük dosyaları
- `~/.omniroute/` dizinindeki tüm dosyalar
> ⚠️ **Warning:** `npm run uninstall:full` is irreversible. All your provider connections, combos, API keys, and usage history will be permanently deleted.
> ⚠️ **Uyarı:** `npm run uninstall:full` işlemi geri alınamaz. Tüm sağlayıcı bağlantılarınız, kombolarınız, API anahtarlarınız ve kullanım geçmişiniz kalıcı olarak silinir.
---
## Manual Uninstall
## Manuel Kaldırma
### NPM Global Install
### NPM Global Kurulumu
```bash
# Remove the global package
# Global paketi kaldırın
npm uninstall -g omniroute
# (Optional) Remove data directory
rm -rf ~/.omniroute
```
### pnpm Global Install
```bash
pnpm uninstall -g omniroute
# (İsteğe bağlı) Veri dizinini silin
rm -rf ~/.omniroute
```
### Docker
```bash
# Stop and remove the container
# Konteyneri durdurun ve silin
docker stop omniroute
docker rm omniroute
# Remove the volume (deletes all data)
# Hacmi kaldırın (tüm verileri siler)
docker volume rm omniroute-data
# (Optional) Remove the image
# (İsteğe bağlı) İmajı silin
docker rmi diegosouzapw/omniroute:latest
```
### Docker Compose
```bash
# Stop and remove containers
# Konteynerleri durdurun ve kaldırın
docker compose down
# Also remove volumes (deletes all data)
# Hacimleri de kaldırın (tüm verileri siler)
docker compose down -v
```
### Electron Desktop App
**Windows:**
- Open `Settings → Apps → OmniRoute → Uninstall`
- Or run the NSIS uninstaller from the install directory
### Electron Masaüstü Uygulaması
**macOS:**
- `OmniRoute.app` uygulamasını `/Applications` dizininden Çöp Sepetine sürükleyin
- Verileri silin: `rm -rf ~/Library/Application Support/omniroute`
- Drag `OmniRoute.app` from `/Applications` to Trash
- Remove data: `rm -rf ~/Library/Application Support/omniroute`
**Windows:**
- `Ayarlar → Uygulamalar → OmniRoute → Kaldır`
**Linux:**
- Remove the AppImage file
- Remove data: `rm -rf ~/.omniroute`
### Source Install (git clone)
```bash
# Remove the cloned directory
rm -rf /path/to/omniroute
# (Optional) Remove data directory
rm -rf ~/.omniroute
```
---
## Data Directories
OmniRoute stores data in the following locations by default:
| Platform | Default Path | Override |
| ------------- | ----------------------------- | ------------------------- |
| Linux | `~/.omniroute/` | `DATA_DIR` env var |
| macOS | `~/.omniroute/` | `DATA_DIR` env var |
| Windows | `%APPDATA%/omniroute/` | `DATA_DIR` env var |
| Docker | `/app/data/` (mounted volume) | `DATA_DIR` env var |
| XDG-compliant | `$XDG_CONFIG_HOME/omniroute/` | `XDG_CONFIG_HOME` env var |
### Files in the data directory
| File/Directory | Description |
| -------------------- | ------------------------------------------------- |
| `storage.sqlite` | Main database (providers, combos, settings, keys) |
| `storage.sqlite-wal` | SQLite write-ahead log (temporary) |
| `storage.sqlite-shm` | SQLite shared memory (temporary) |
| `call_logs/` | Request payload archives |
| `backups/` | Automatic database backups |
| `log.txt` | Legacy request log (optional) |
---
## Verify Complete Removal
After uninstalling, verify there are no remaining files:
```bash
# Check for global npm package
npm list -g omniroute 2>/dev/null
# Check for data directory
ls -la ~/.omniroute/ 2>/dev/null
# Check for running processes
pgrep -f omniroute
```
If any process is still running, stop it:
```bash
pkill -f omniroute
```
- AppImage veya paket yöneticisi üzerinden kaldırın
- Verileri silin: `rm -rf ~/.config/omniroute`

File diff suppressed because it is too large Load Diff

View File

@@ -1,170 +1,37 @@
# Test Coverage Plan (Türkçe)
---
title: "Test Kapsam Planı"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇧🇩 [bn](../../bn/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇮🇷 [fa](../../fa/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇮🇳 [gu](../../gu/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇮🇳 [hi](../../hi/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇮🇳 [mr](../../mr/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇰🇪 [sw](../../sw/docs/COVERAGE_PLAN.md) · 🇮🇳 [ta](../../ta/docs/COVERAGE_PLAN.md) · 🇮🇳 [te](../../te/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇹🇷 [tr](../../tr/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇵🇰 [ur](../../ur/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md)
# Test Kapsam Planı (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/ops/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/ops/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/ops/COVERAGE_PLAN.md) · 🇧🇩 [bn](../../bn/docs/ops/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/ops/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/ops/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/ops/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/ops/COVERAGE_PLAN.md) · 🇮🇷 [fa](../../fa/docs/ops/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/ops/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/ops/COVERAGE_PLAN.md) · 🇮🇳 [gu](../../gu/docs/ops/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/ops/COVERAGE_PLAN.md) · 🇮🇳 [hi](../../hi/docs/ops/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/ops/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/ops/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/ops/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/ops/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/ops/COVERAGE_PLAN.md) · 🇮🇳 [mr](../../mr/docs/ops/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/ops/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/ops/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/ops/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/ops/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/ops/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/ops/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ops/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/ops/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/ops/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/ops/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/ops/COVERAGE_PLAN.md) · 🇰🇪 [sw](../../sw/docs/ops/COVERAGE_PLAN.md) · 🇮🇳 [ta](../../ta/docs/ops/COVERAGE_PLAN.md) · 🇮🇳 [te](../../te/docs/ops/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/ops/COVERAGE_PLAN.md) · 🇹🇷 [tr](../../tr/docs/ops/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ops/COVERAGE_PLAN.md) · 🇵🇰 [ur](../../ur/docs/ops/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/ops/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ops/COVERAGE_PLAN.md)
---
Last updated: 2026-03-28
## Taban Çizgisi
## Baseline
| Metrik | Kapsam | İfadeler / Satırlar | Dallar | Fonksiyonlar | Notlar |
| -------------------- | ----------------------------------------------------- | ------------------: | -------: | -----------: | --------------------------------------------------- |
| Önerilen taban çizgi | Yalnızca kaynak kod, testler hariç, `open-sse` dahil | 82.58% | 75.22% | 84.23% | İyileştirilecek proje genelindeki taban çizgisidir |
There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
## Kurallar
| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
- Kapsam hedefleri `tests/**` için değil, kaynak dosyalar için geçerlidir.
- `open-sse/**` ürünün bir parçasıdır ve kapsamda kalmalıdır.
- Yeni kod, dokunulan alanlardaki kapsamı düşürmemelidir.
- Uygulama ayrıntıları yerine davranış ve dal sonuçlarını test etmeyi tercih edin.
- `src/lib/db/**` için geniş mock'lar yerine geçici SQLite veritabanlarını ve küçük fikstürleri tercih edin.
The recommended baseline is the number to optimize against.
## Aşamalar
## Rules
- Coverage targets apply to source files, not to `tests/**`.
- `open-sse/**` is part of the product and must remain in scope.
- New code should not reduce coverage in touched areas.
- Prefer testing behavior and branch outcomes over implementation details.
- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
## Current command set
- `npm run test:coverage`
- Main source coverage gate for the unit test suite
- Generates `text-summary`, `html`, `json-summary`, and `lcov`
- `npm run coverage:report`
- Detailed file-by-file report from the latest run
- `npm run test:coverage:legacy`
- Historical comparison only
## Milestones
| Phase | Target | Focus |
| ------- | ---------------------: | ------------------------------------------------- |
| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
| Phase 2 | 65% statements / lines | DB and route foundations |
| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
## Priority hotspots
These files or areas offer the best return for the next phases:
1. `open-sse/handlers`
- `chatCore.ts` at 7.57%
- Overall directory at 29.07%
2. `open-sse/translator/request`
- Overall directory at 36.39%
- Many translators are still near single-digit coverage
3. `open-sse/translator/response`
- Overall directory at 8.07%
4. `open-sse/executors`
- Overall directory at 36.62%
5. `src/lib/db`
- `models.ts` at 20.66%
- `registeredKeys.ts` at 34.46%
- `modelComboMappings.ts` at 36.25%
- `settings.ts` at 46.40%
- `webhooks.ts` at 33.33%
6. `src/lib/usage`
- `usageHistory.ts` at 21.12%
- `usageStats.ts` at 9.56%
- `costCalculator.ts` at 30.00%
7. `src/lib/providers`
- `validation.ts` at 41.16%
8. Low-risk utility and API files for early gains
- `src/shared/utils/upstreamError.ts`
- `src/shared/utils/apiAuth.ts`
- `src/lib/api/errorResponse.ts`
- `src/app/api/settings/require-login/route.ts`
- `src/app/api/providers/[id]/models/route.ts`
## Execution checklist
### Phase 1: 56.95% -> 60%
- [x] Fix coverage metric so it reflects source code instead of test files
- [x] Keep a legacy coverage script for comparison
- [x] Record the baseline and hotspots in-repo
- [ ] Add focused tests for low-risk utilities:
- `src/shared/utils/upstreamError.ts`
- `src/shared/utils/fetchTimeout.ts`
- `src/lib/api/errorResponse.ts`
- `src/shared/utils/apiAuth.ts`
- `src/lib/display/names.ts`
- [ ] Add route tests for:
- `src/app/api/settings/require-login/route.ts`
- `src/app/api/providers/[id]/models/route.ts`
### Phase 2: 60% -> 65%
- [ ] Add DB-backed tests for:
- `src/lib/db/modelComboMappings.ts`
- `src/lib/db/settings.ts`
- `src/lib/db/registeredKeys.ts`
- [ ] Cover branch behavior in:
- `src/lib/providers/validation.ts`
- `src/app/api/v1/embeddings/route.ts`
- `src/app/api/v1/moderations/route.ts`
### Phase 3: 65% -> 70%
- [ ] Add usage analytics tests for:
- `src/lib/usage/usageHistory.ts`
- `src/lib/usage/usageStats.ts`
- `src/lib/usage/costCalculator.ts`
- [ ] Expand route coverage for proxy management and settings branches
### Phase 4: 70% -> 75%
- [ ] Cover translator helpers and central translation paths:
- `open-sse/translator/index.ts`
- `open-sse/translator/helpers/*`
- `open-sse/translator/request/*`
- `open-sse/translator/response/*`
### Phase 5: 75% -> 80%
- [ ] Add handler-level tests for:
- `open-sse/handlers/chatCore.ts`
- `open-sse/handlers/responsesHandler.js`
- `open-sse/handlers/imageGeneration.js`
- `open-sse/handlers/embeddings.js`
- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
### Phase 6: 80% -> 85%
- [ ] Merge more edge-case suites into the main coverage path
- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
### Phase 7: 85% -> 90%
- [ ] Treat the remaining low-coverage files as blockers
- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
## Ratchet policy
Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
Recommended ratchet sequence:
1. 55/60/55
2. 60/62/58
3. 65/64/62
4. 70/66/66
5. 75/70/72
6. 80/75/78
7. 85/80/84
8. 90/85/88
Order is `statements-lines / branches / functions`.
## Known gap
The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
| Aşama | Hedef | Odak Alanı | Durum |
| ------- | --------------------: | ------------------------------------------------- | ------------ |
| Aşama 1 | %60 ifadeler / satır | Hızlı kazanımlar ve düşük riskli yardımcılar | ✅ Tamamlandı|
| Aşama 2 | %65 ifadeler / satır | Veritabanı ve rota temelleri | ✅ Tamamlandı|
| Aşama 3 | %70 ifadeler / satır | Sağlayıcı doğrulaması ve kullanım analitiği | ✅ Tamamlandı|
| Aşama 4 | %75 ifadeler / satır | `open-sse` çevirmenleri ve yardımcıları | ✅ Tamamlandı|
| Aşama 5 | %80 ifadeler / satır | `open-sse` işleyicileri ve yürütücü dalları | ✅ Tamamlandı|
| Aşama 6 | %85 ifadeler / satır | Uç durumlar, dal borcu, regresyon paketleri | Devam ediyor |
| Aşama 7 | %90 ifadeler / satır | Son tarama, boşluk kapatma, sıkı kalite kapısı | Bekliyor |

View File

@@ -1,455 +1,58 @@
# OmniRoute Fly.io 部署指南 (Türkçe)
---
title: "OmniRoute Fly.io Dağıtım Kılavuzu"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇧🇩 [bn](../../bn/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇷 [fa](../../fa/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [gu](../../gu/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [hi](../../hi/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [mr](../../mr/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇰🇪 [sw](../../sw/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [ta](../../ta/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [te](../../te/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇹🇷 [tr](../../tr/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇰 [ur](../../ur/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FLY_IO_DEPLOYMENT_GUIDE.md)
# OmniRoute Fly.io Dağıtım Kılavuzu (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇧🇩 [bn](../../bn/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇷 [fa](../../fa/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [gu](../../gu/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [hi](../../hi/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [mr](../../mr/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇰🇪 [sw](../../sw/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [ta](../../ta/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇮🇳 [te](../../te/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇹🇷 [tr](../../tr/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇵🇰 [ur](../../ur/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md)
---
本文档记录 OmniRoute Fly.io 上的实际部署方法,适用于两类场景:
- 首次把当前项目部署到 Fly.io
- 后续代码更新后继续发布
- 新项目参考同样流程部署
本文基于当前项目已经验证通过的配置整理,应用名为 `omniroute`
Bu belge, OmniRoute'un Fly.io platformunda dağıtım sürecini adım adım açıklar.
---
## 1. 部署目标
## 1. Dağıtım Hedefleri
- 平台:Fly.io
- 部署方式:本地 `flyctl` 直接发布
- 运行方式:使用仓库内现有 `Dockerfile` `fly.toml`
- 数据持久化Fly Volume 挂载到 `/data`
- 访问地址:`https://omniroute.fly.dev/`
- **Platform:** Fly.io
- **Dağıtım yöntemi:** Yerel `flyctl` ile doğrudan yayınlama
- **Çalışma Zamanı:** Depodaki mevcut `Dockerfile` ve `fly.toml`
- **Veri Kalıcılığı:** `/data` dizinine bağlanmış Fly Volume
- **Erişim Adresi:** `https://omniroute.fly.dev/`
---
## 2. 当前项目关键配置
## 2. Ön Koşullar ve `flyctl` Kurulumu
当前仓库中的 `fly.toml` 已确认包含以下关键项:
```bash
# Fly CLI kurulumu (macOS / Linux):
curl -L https://fly.io/install.sh | sh
```toml
app = 'omniroute'
primary_region = 'sin'
[[mounts]]
source = 'data'
destination = '/data'
[processes]
app = 'node run-standalone.mjs'
[http_service]
internal_port = 20128
[env]
TZ = "Asia/Shanghai"
HOST = "0.0.0.0"
HOSTNAME = "0.0.0.0"
BIND = "0.0.0.0"
```
说明:
- `app = 'omniroute'` 决定实际部署到哪个 Fly 应用
- `destination = '/data'` 决定持久卷挂载目录
- 本项目必须让 `DATA_DIR=/data`,否则数据库和密钥会写到容器临时目录
---
## 3. 必备工具
### 3.1 安装 Fly CLI
Windows PowerShell
```powershell
pwsh -Command "iwr https://fly.io/install.ps1 -useb | iex"
```
如果安装脚本在当前环境失败,也可以手动下载 `flyctl` 二进制并放到 `PATH` 中。
### 3.2 登录 Fly 账号
```powershell
# Giriş yapma:
flyctl auth login
```
### 3.3 检查登录状态
```powershell
flyctl auth whoami
flyctl version
```
---
## 4. 首次部署当前项目
### 4.1 获取代码并进入目录
```powershell
git clone https://github.com/diegosouzapw/OmniRoute.git
cd OmniRoute
```
### 4.2 确认应用名
打开 `fly.toml`,重点看这一行:
```toml
app = 'omniroute'
```
如果你准备部署到自己的新应用,可改成全局唯一名称,例如:
```toml
app = 'omniroute-yourname'
```
注意:
- 控制台里要看的是与 `fly.toml``app` 一致的应用
- 以前如果用过别的名字,例如 `oroute`,不要和 `omniroute` 混淆
### 4.3 创建应用
如果该应用尚不存在:
```powershell
flyctl apps create omniroute
```
如果你已经改成别的应用名,把 `omniroute` 替换成你的名字。
### 4.4 首次部署
```powershell
flyctl deploy
```
---
## 5. 必配参数
本项目在 Fly.io 上建议至少配置以下参数。
### 5.1 已验证使用的参数
这些参数已经在当前 `omniroute` 应用上实际部署:
- `API_KEY_SECRET`
- `DATA_DIR`
- `JWT_SECRET`
- `MACHINE_ID_SALT`
- `NEXT_PUBLIC_BASE_URL`
- `STORAGE_ENCRYPTION_KEY`
### 5.2 关于 `INITIAL_PASSWORD`
当前项目没有设置 `INITIAL_PASSWORD`,因为本次部署按需求不使用它。
如果不设置:
- 启动日志会提示默认密码是 `CHANGEME`
- 部署后应尽快在系统设置中修改登录密码
如果你希望无人值守初始化后台密码,也可以后续补:
- `INITIAL_PASSWORD`
---
## 6. 推荐参数说明
### 6.1 Secrets 中设置
建议放入 Fly Secrets
| 变量名 | 是否推荐 | 说明 |
| ------------------------ | -------- | ------------------------------ |
| `API_KEY_SECRET` | 必需 | API Key 生成与校验使用 |
| `JWT_SECRET` | 必需 | 登录态和 JWT 签名使用 |
| `STORAGE_ENCRYPTION_KEY` | 强烈推荐 | 加密存储敏感连接信息 |
| `MACHINE_ID_SALT` | 推荐 | 生成稳定机器标识 |
| `INITIAL_PASSWORD` | 可选 | 首次部署时直接指定后台初始密码 |
| OAuth/API 私密凭证 | 按需 | 各类外部平台鉴权配置 |
### 6.2 当前项目推荐值
| 变量名 | 推荐值 |
| ---------------------- | --------------------------- |
| `DATA_DIR` | `/data` |
| `NEXT_PUBLIC_BASE_URL` | `https://omniroute.fly.dev` |
说明:
- `DATA_DIR=/data` 非常关键,必须与 Fly Volume 挂载点一致
- `NEXT_PUBLIC_BASE_URL` 用于调度器和前端回调等场景
---
## 7. 一键设置参数
下面命令会生成安全随机值,并把当前项目需要的参数一次性写入 Fly Secrets。
说明:
- 不包含 `INITIAL_PASSWORD`
- 适用于当前项目 `omniroute`
```powershell
$apiKeySecret = [Convert]::ToHexString((1..32 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 })).ToLower()
$jwtSecret = [Convert]::ToHexString((1..64 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 })).ToLower()
$machineIdSalt = [Convert]::ToHexString((1..32 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 })).ToLower()
$storageKey = [Convert]::ToHexString((1..32 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 })).ToLower()
flyctl secrets set `
API_KEY_SECRET=$apiKeySecret `
JWT_SECRET=$jwtSecret `
MACHINE_ID_SALT=$machineIdSalt `
STORAGE_ENCRYPTION_KEY=$storageKey `
DATA_DIR=/data `
NEXT_PUBLIC_BASE_URL=https://omniroute.fly.dev `
-a omniroute
```
如果你还要加初始密码:
```powershell
flyctl secrets set INITIAL_PASSWORD=你的强密码 -a omniroute
```
---
## 8. 查看当前参数
```powershell
flyctl secrets list -a omniroute
```
如果控制台 `Secrets` 页面没有显示你期待的变量,先检查:
- 看的应用是不是 `omniroute`
- `fly.toml``app` 是否和控制台应用一致
---
## 9. 后续更新发布
代码有更新后,发布步骤很简单:
```powershell
git pull
flyctl deploy
```
如果只更新参数,不改代码:
```powershell
flyctl secrets set KEY=value -a omniroute
```
Fly 会自动滚动更新机器。
### 9.1 跟踪原仓库更新并保留 fork 的 `fly.toml`
如果当前仓库是 fork并且你要同步上游 `https://github.com/diegosouzapw/OmniRoute` 的更新,推荐按下面流程执行。
先确认远程:
```powershell
git remote -v
```
应至少包含:
- `origin` 指向你自己的 fork
- `upstream` 指向原仓库
如果没有 `upstream`,先添加:
```powershell
git remote add upstream https://github.com/diegosouzapw/OmniRoute.git
```
同步上游前,先抓取最新提交和标签:
```powershell
git fetch upstream --tags
```
查看当前版本和上游标签:
```powershell
git describe --tags --always
git show --no-patch --oneline v3.4.7
```
如果你想合并上游最新 `main`,并强制保留 fork 当前的 `fly.toml`,可按下面流程执行:
```powershell
git merge upstream/main
git checkout HEAD~1 -- fly.toml
git add -- fly.toml
git commit -m "chore(deploy): keep fork fly.toml"
git push origin main
```
说明:
- `git merge upstream/main` 用于同步原仓库最新代码
- `git checkout HEAD~1 -- fly.toml` 用于恢复合并前你 fork 自己的 `fly.toml`
- 如果上游没有改 `fly.toml`,这一步不会带来额外差异
- 如果上游改了 `fly.toml`,这一步能确保 Fly 应用名、挂载卷、区域等 fork 自定义部署配置不被覆盖
如果你明确只想对齐某个发布标签,例如 `v3.4.7`,也可以先确认标签是否已经包含在 `upstream/main`
```powershell
git merge-base --is-ancestor v3.4.7 upstream/main
```
返回成功表示 `upstream/main` 已经包含该版本,直接合并 `upstream/main` 即可。
### 9.2 同步上游后的标准发布顺序
同步原仓库完成后,推荐按下面顺序发布:
1. `git fetch upstream --tags`
2. `git merge upstream/main`
3. 恢复 fork 的 `fly.toml`
4. `git push origin main`
5. `flyctl deploy`
6. `flyctl status -a omniroute`
7. `flyctl logs --no-tail -a omniroute`
这就是当前项目升级到 `v3.4.7` 时使用的实际流程。
---
## 10. 发布后检查
### 10.1 查看应用状态
```powershell
flyctl status -a omniroute
```
### 10.2 查看启动日志
```powershell
flyctl logs --no-tail -a omniroute
```
### 10.3 检查网站可访问
```powershell
try {
(Invoke-WebRequest -Uri "https://omniroute.fly.dev" -MaximumRedirection 5 -UseBasicParsing).StatusCode
} catch {
if ($_.Exception.Response) {
$_.Exception.Response.StatusCode.value__
} else {
throw
}
}
```
返回 `200` 说明站点已正常响应。
---
## 11. 成功标志
部署成功后,日志里应看到类似内容:
```text
[bootstrap] Secrets persisted to: /data/server.env
[DB] SQLite database ready: /data/storage.sqlite
```
这两个点很关键:
- `/data/server.env` 说明运行时密钥落到了持久卷
- `/data/storage.sqlite` 说明数据库写入持久卷
如果你看到的是 `/app/data/...`,说明 `DATA_DIR` 没配对,需要立即修正。
---
## 12. 常见问题
### 12.1 `Secrets` 页面是空的
通常有两种原因:
- 你还没执行 `flyctl secrets set`
- 你打开的是另一个应用,例如 `oroute`,不是 `omniroute`
### 12.2 `flyctl deploy` 报 `app not found`
先创建应用:
```powershell
flyctl apps create omniroute
```
### 12.3 `fly.toml` 解析失败
重点检查:
- 注释里是否有乱码字符
- TOML 引号和缩进是否正确
### 12.4 数据没有持久化
检查以下两点:
- `fly.toml` 中是否存在 `destination = '/data'`
- `DATA_DIR` 是否设置为 `/data`
### 12.5 不设置 `INITIAL_PASSWORD` 是否能跑
可以运行,但会回退到默认 `CHANGEME`。生产环境建议尽快修改后台密码。
---
## 13. 新项目复用建议
如果以后是新项目照着这份文档部署,最少改这几项:
1. 修改 `fly.toml` 里的 `app`
2. 修改 `NEXT_PUBLIC_BASE_URL`
3. 保持 `DATA_DIR=/data`
4. 重新生成 `API_KEY_SECRET``JWT_SECRET``MACHINE_ID_SALT``STORAGE_ENCRYPTION_KEY`
5. 首次部署后检查日志是否写入 `/data`
不要直接复用旧项目的密钥。
---
## 14. 当前项目的最小发布清单
当前项目后续最常用的命令如下:
```powershell
flyctl auth whoami
flyctl status -a omniroute
flyctl secrets list -a omniroute
flyctl deploy
flyctl logs --no-tail -a omniroute
```
如果只是正常发版,核心就是:
```powershell
flyctl deploy
```
如果是新环境首次部署,核心就是:
1. `flyctl auth login`
2. `flyctl apps create omniroute`
3. `flyctl secrets set ... -a omniroute`
4. `flyctl deploy`
5. `flyctl logs --no-tail -a omniroute`
## 3. İlk Dağıtım Adımları
1. **Volume Oluşturma (Kalıcı Depolama):**
```bash
flyctl volumes create data --size 3 --region sin
```
2. **Gizli Değişkenleri (Secrets) Ayarlama:**
```bash
flyctl secrets set \
JWT_SECRET="guclu-jwt-anahtariniz" \
API_KEY_SECRET="guclu-aes-anahtariniz" \
INITIAL_PASSWORD="yonetici-sifreniz" \
DATA_DIR="/data"
```
3. **Uygulamayı Dağıtma:**
```bash
flyctl deploy
```

View File

@@ -1,44 +1,53 @@
# Release Checklist (Türkçe)
---
title: "Sürüm Kontrol Listesi (Release Checklist)"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇧🇩 [bn](../../bn/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇮🇷 [fa](../../fa/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [gu](../../gu/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [hi](../../hi/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [mr](../../mr/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇰🇪 [sw](../../sw/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [ta](../../ta/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [te](../../te/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇹🇷 [tr](../../tr/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇵🇰 [ur](../../ur/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md)
# Sürüm Kontrol Listesi (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/ops/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/ops/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/ops/RELEASE_CHECKLIST.md) · 🇧🇩 [bn](../../bn/docs/ops/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/ops/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/ops/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/ops/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇷 [fa](../../fa/docs/ops/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/ops/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [gu](../../gu/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [hi](../../hi/docs/ops/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/ops/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/ops/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [mr](../../mr/docs/ops/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/ops/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ops/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/ops/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/ops/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/ops/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/ops/RELEASE_CHECKLIST.md) · 🇰🇪 [sw](../../sw/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [ta](../../ta/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [te](../../te/docs/ops/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/ops/RELEASE_CHECKLIST.md) · 🇹🇷 [tr](../../tr/docs/ops/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇰 [ur](../../ur/docs/ops/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/ops/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ops/RELEASE_CHECKLIST.md)
---
Use this checklist before tagging or publishing a new OmniRoute release.
## Version and Changelog
1. Bump `package.json` version (`x.y.z`) in the release branch.
2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- `## [x.y.z] — YYYY-MM-DD`
3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
## API Docs
1. Update `docs/reference/openapi.yaml`:
- `info.version` must equal `package.json` version.
2. Validate endpoint examples if API contracts changed.
## Runtime Docs
1. Review `docs/architecture/ARCHITECTURE.md` for storage/runtime drift.
2. Review `docs/guides/TROUBLESHOOTING.md` for env var and operational drift.
3. Verify the release/runtime Node.js version still satisfies the supported secure floor:
- `>=20.20.2 <21` or `>=22.22.2 <23`
- `npm run check:node-runtime`
4. Validate the npm publish artifact after building the standalone package:
- `npm run build:cli`
- `npm run check:pack-artifact`
- confirm no `app.__qa_backup`, `scripts/scratch`, `package-lock.json`, or other local residue
5. Update localized docs if source docs changed significantly.
## Automated Check
Run the sync guard locally before opening PR:
## Özet Akış
```bash
npm run check:docs-sync
# 1. Sürümü artırın + CHANGELOG oluşturun
/version-bump-cc patch # veya minor/major
# 2. Kalite kapısını yerel olarak çalıştırın
npm run check # lint + testler
npm run test:coverage # tam kapsam kapısı (60/60/60/60)
# 3. Derleme & Başlatma Testi
npm run build
npm run test:e2e # isteğe bağlı ancak önerilir
# 4. Sürüm oluşturma
/generate-release-cc
# 5. Dağıtım
/deploy-vps-both-cc # veya akamai-cc / local-cc
# 6. Sürüm kanıtlarını yakalama
/capture-release-evidences-cc
```
CI also runs this check in `.github/workflows/ci.yml` (lint job).
---
## Aşamalı Yayınlama (npm Staged Publishing)
npm-publish iş akışı doğrudan yayınlama yapmaz: paketlenmiş tarball'ı (`check:pack-boot`) başlatır ve ardından `npm stage publish` çalıştırır — tam baytlar kayıt defterine park edilir, **sahibi onaylayana kadar kurulamaz**. İnsan 2FA kapısı kanıttan SONRA gelir.
### Onay Akışı
1. `npm stage list omniroute` — aşama kimliğini (stage id) bulun.
2. Paketlenmiş baytları doğrulayın: `npm stage download <id>`, ardından geçici bir dizine kurun ve başlatın (`npm run check:pack-boot`).
3. `npm stage approve <id>` — 2FA istemi yayını tamamlar. `npm stage reject <id>` iptal eder.
---
## Acil Düzeltme Hızlı Şeridi (`hotfix` Etiketi)
`hotfix` etiketli bir PR, ağır CI matrisini (9 parçalı E2E, kapsam kontrolü) atlar ve hızlı, yüksek sinyalli kapıları korur: build, unit, integration, vitest, lint/typecheck, docs-sync, `check:pack-artifact` ve tarball boot-smoke (`check:pack-boot`). Hedef: ~33 dakika yerine ≤15 dakikada yeşil.

View File

@@ -1,407 +1,80 @@
# OmniRoute — Deployment Guide on VM with Cloudflare (Türkçe)
---
title: "OmniRoute — Cloudflare ile VM Üzerinde Dağıtım Kılavuzu"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇩 [bn](../../bn/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇷 [fa](../../fa/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [gu](../../gu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [hi](../../hi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [mr](../../mr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇪 [sw](../../sw/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [ta](../../ta/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [te](../../te/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇷 [tr](../../tr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇰 [ur](../../ur/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md)
# OmniRoute — Cloudflare ile VM Üzerinde Dağıtım Kılavuzu (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇧🇩 [bn](../../bn/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇮🇷 [fa](../../fa/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [gu](../../gu/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [hi](../../hi/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [mr](../../mr/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇰🇪 [sw](../../sw/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [ta](../../ta/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [te](../../te/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇹🇷 [tr](../../tr/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇵🇰 [ur](../../ur/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/ops/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ops/VM_DEPLOYMENT_GUIDE.md)
---
Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
Cloudflare üzerinden yönetilen bir alan adı ile VM (VPS) üzerinde OmniRoute kurulumu ve yapılandırması için eksiksiz kılavuz.
---
## Prerequisites
## Ön Koşullar
| Item | Minimum | Recommended |
| Öğe | Minimum | Önerilen |
| ---------- | ------------------------ | ---------------- |
| **CPU** | 1 vCPU | 2 vCPU |
| **RAM** | 1 GB | 2 GB |
| **Disk** | 10 GB SSD | 25 GB SSD |
| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
| **Domain** | Registered on Cloudflare | — |
| **İşletim Sistemi** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
| **Alan Adı** | Cloudflare'e yönlendirilmiş | — |
| **Docker** | Docker Engine 24+ | Docker 27+ |
**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
---
## 1. Configure the VM
## 1. VM Yapılandırması
### 1.1 Create the instance
On your preferred VPS provider:
- Choose Ubuntu 24.04 LTS
- Select the minimum plan (1 vCPU / 1 GB RAM)
- Set a strong root password or configure SSH key
- Note the **public IP** (e.g., `203.0.113.10`)
### 1.2 Connect via SSH
### 1.1 SSH ile Bağlantı
```bash
ssh root@203.0.113.10
ssh root@SUNUCU_IP_ADRESINIZ
```
### 1.3 Update the system
### 1.2 Sistemi Güncelleme
```bash
apt update && apt upgrade -y
```
### 1.4 Install Docker
### 1.3 Docker Kurulumu
```bash
# Install dependencies
apt install -y ca-certificates curl gnupg
# Add official Docker repository
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
```
### 1.5 Install nginx
```bash
apt install -y nginx
```
### 1.6 Configure Firewall (UFW)
### 1.4 Güvenlik Duvarı (UFW)
```bash
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp # SSH
ufw allow 80/tcp # HTTP (redirect)
ufw allow 80/tcp # HTTP
ufw allow 443/tcp # HTTPS
ufw enable
```
> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
---
## 2. Install OmniRoute
### 2.1 Create configuration directory
## 2. OmniRoute Kurulumu
```bash
mkdir -p /opt/omniroute
cd /opt/omniroute
```
### 2.2 Create environment variables file
Docker Compose ile OmniRoute'u başlatın:
```bash
cat > /opt/omniroute/.env << EOF
# === Security ===
JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
INITIAL_PASSWORD=YourSecurePassword123!
API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
STORAGE_ENCRYPTION_KEY_VERSION=v1
MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
# === App ===
PORT=20128
NODE_ENV=production
HOSTNAME=0.0.0.0
DATA_DIR=/app/data
STORAGE_DRIVER=sqlite
APP_LOG_TO_FILE=true
AUTH_COOKIE_SECURE=false
REQUIRE_API_KEY=false
# === Domain (change to your domain) ===
BASE_URL=https://llms.seudominio.com
NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
# === Cloud Sync (optional) ===
# CLOUD_URL=https://cloud.omniroute.online
# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
EOF
docker compose up -d
```
> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
### 2.3 Start the container
```bash
docker pull diegosouzapw/omniroute:latest
docker run -d \
--name omniroute \
--restart unless-stopped \
--env-file /opt/omniroute/.env \
-p 20128:20128 \
-v omniroute-data:/app/data \
diegosouzapw/omniroute:latest
```
### 2.4 Verify that it is running
```bash
docker ps | grep omniroute
docker logs omniroute --tail 20
```
It should display: `[DB] SQLite database ready` and `listening on port 20128`.
---
## 3. Configure nginx (Reverse Proxy)
### 3.1 Generate SSL certificate (Cloudflare Origin)
In the Cloudflare dashboard:
1. Go to **SSL/TLS → Origin Server**
2. Click **Create Certificate**
3. Keep the defaults (15 years, \*.yourdomain.com)
4. Copy the **Origin Certificate** and the **Private Key**
```bash
mkdir -p /etc/nginx/ssl
# Paste the certificate
nano /etc/nginx/ssl/origin.crt
# Paste the private key
nano /etc/nginx/ssl/origin.key
chmod 600 /etc/nginx/ssl/origin.key
```
### 3.2 Nginx Configuration
```bash
cat > /etc/nginx/sites-available/omniroute << NGINX
# Default server — blocks direct access via IP
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/nginx/ssl/origin.crt;
ssl_certificate_key /etc/nginx/ssl/origin.key;
server_name _;
return 444;
}
# OmniRoute — HTTPS
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name llms.yourdomain.com; # Change to your domain
ssl_certificate /etc/nginx/ssl/origin.crt;
ssl_certificate_key /etc/nginx/ssl/origin.key;
ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 100M;
location / {
proxy_pass http://127.0.0.1:20128;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;
# SSE (Server-Sent Events) — streaming AI responses
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
}
# HTTP → HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name llms.yourdomain.com;
return 301 https://$server_name$request_uri;
}
NGINX
```
Keep reverse-proxy stream timeouts aligned with your OmniRoute timeout env vars. If you raise
`FETCH_TIMEOUT_MS` / `STREAM_IDLE_TIMEOUT_MS`, raise `proxy_read_timeout` / `proxy_send_timeout`
above the same threshold.
### 3.3 Enable and Test
```bash
# Remove default configuration
rm -f /etc/nginx/sites-enabled/default
# Enable OmniRoute
ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
# Test and reload
nginx -t && systemctl reload nginx
```
---
## 4. Configure Cloudflare DNS
### 4.1 Add DNS record
In the Cloudflare dashboard → DNS:
| Type | Name | Content | Proxy |
| ---- | ------ | ---------------------- | ---------- |
| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
### 4.2 Configure SSL
Under **SSL/TLS → Overview**:
- Mode: **Full (Strict)**
Under **SSL/TLS → Edge Certificates**:
- Always Use HTTPS: ✅ On
- Minimum TLS Version: TLS 1.2
- Automatic HTTPS Rewrites: ✅ On
### 4.3 Testing
```bash
curl -sI https://llms.seudominio.com/health
# Should return HTTP/2 200
```
---
## 5. Operations and Maintenance
### Upgrade to a new version
```bash
docker pull diegosouzapw/omniroute:latest
docker stop omniroute && docker rm omniroute
docker run -d --name omniroute --restart unless-stopped \
--env-file /opt/omniroute/.env \
-p 20128:20128 \
-v omniroute-data:/app/data \
diegosouzapw/omniroute:latest
```
### View logs
```bash
docker logs -f omniroute # Real-time stream
docker logs omniroute --tail 50 # Last 50 lines
```
### Manual database backup
```bash
# Copy data from the volume to the host
docker cp omniroute:/app/data ./backup-$(date +%F)
# Or compress the entire volume
docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
```
### Restore from backup
```bash
docker stop omniroute
docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
docker start omniroute
```
---
## 6. Advanced Security
### Restrict nginx to Cloudflare IPs
```bash
cat > /etc/nginx/cloudflare-ips.conf << CF
# Cloudflare IPv4 ranges — update periodically
# https://www.cloudflare.com/ips-v4/
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
real_ip_header CF-Connecting-IP;
CF
```
Add the following to `nginx.conf` inside the `http {}` block:
```nginx
include /etc/nginx/cloudflare-ips.conf;
```
### Install fail2ban
```bash
apt install -y fail2ban
systemctl enable fail2ban
systemctl start fail2ban
# Check status
fail2ban-client status sshd
```
### Block direct access to the Docker port
```bash
# Prevent direct external access to port 20128
iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
# Persist the rules
apt install -y iptables-persistent
netfilter-persistent save
```
---
## 7. Deploy to Cloudflare Workers (Optional)
For remote access via Cloudflare Workers (without exposing the VM directly):
```bash
# In the local repository
cd omnirouteCloud
npm install
npx wrangler login
npx wrangler deploy
```
See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
---
## Port Summary
| Port | Service | Access |
| ----- | ----------- | -------------------------- |
| 22 | SSH | Public (with fail2ban) |
| 80 | nginx HTTP | Redirect → HTTPS |
| 443 | nginx HTTPS | Via Cloudflare Proxy |
| 20128 | OmniRoute | Localhost only (via nginx) |

View File

@@ -1,28 +1,42 @@
# API Reference (Türkçe)
---
title: "API Referansı"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇧🇩 [bn](../../bn/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇮🇷 [fa](../../fa/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇮🇳 [gu](../../gu/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇮🇳 [hi](../../hi/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇮🇳 [mr](../../mr/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇰🇪 [sw](../../sw/docs/API_REFERENCE.md) · 🇮🇳 [ta](../../ta/docs/API_REFERENCE.md) · 🇮🇳 [te](../../te/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇹🇷 [tr](../../tr/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇵🇰 [ur](../../ur/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md)
# API Referansı (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/reference/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/reference/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/reference/API_REFERENCE.md) · 🇧🇩 [bn](../../bn/docs/reference/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/reference/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/reference/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/reference/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/reference/API_REFERENCE.md) · 🇮🇷 [fa](../../fa/docs/reference/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/reference/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/reference/API_REFERENCE.md) · 🇮🇳 [gu](../../gu/docs/reference/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/reference/API_REFERENCE.md) · 🇮🇳 [hi](../../hi/docs/reference/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/reference/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/reference/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/reference/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/reference/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/reference/API_REFERENCE.md) · 🇮🇳 [mr](../../mr/docs/reference/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/reference/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/reference/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/reference/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/reference/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/reference/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/reference/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/reference/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/reference/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/reference/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/reference/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/reference/API_REFERENCE.md) · 🇰🇪 [sw](../../sw/docs/reference/API_REFERENCE.md) · 🇮🇳 [ta](../../ta/docs/reference/API_REFERENCE.md) · 🇮🇳 [te](../../te/docs/reference/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/reference/API_REFERENCE.md) · 🇹🇷 [tr](../../tr/docs/reference/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/reference/API_REFERENCE.md) · 🇵🇰 [ur](../../ur/docs/reference/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/reference/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/reference/API_REFERENCE.md)
---
Complete reference for all OmniRoute API endpoints.
Tüm OmniRoute API uç noktaları için eksiksiz referans dokümantasyonu.
---
## Table of Contents
## İçindekiler
- [Chat Completions](#chat-completions)
- [Embeddings](#embeddings)
- [Image Generation](#image-generation)
- [List Models](#list-models)
- [Compatibility Endpoints](#compatibility-endpoints)
- [Semantic Cache](#semantic-cache)
- [Dashboard & Management](#dashboard--management)
- [Request Processing](#request-processing)
- [Authentication](#authentication)
- [Sohbet Tamamlama (Chat Completions)](#sohbet-tamamlama-chat-completions)
- [Özel Başlıklar (Custom Headers)](#özel-başlıklar)
- [Gömme (Embeddings)](#gömme-embeddings)
- [Görsel Üretimi (Image Generation)](#görsel-üretimi)
- [Ses ve Medya API'leri](#ses-ve-medya-apileri)
- [Modelleri Listeleme (List Models)](#modelleri-listeleme)
- [Uyumluluk Uç Noktaları](#uyumluluk-uç-noktaları)
- [Arama API'si (Search API)](#arama-apisi)
- [WebSocket Akışı](#websocket-akışı)
- [Anlamsal Önbellek (Semantic Cache)](#anlamsal-önbellek)
- [Pano ve Yönetim API'leri](#pano-ve-yönetim-apileri)
- [Kombo Yönetimi](#kombo-yönetimi)
- [Webhook'lar](#webhooklar)
- [Kayıtlı Anahtarlar (Otomatik Yönetim)](#kayıtlı-anahtarlar)
- [Ajanlar Protokolü (ACP)](#ajanlar-protokolü)
- [Yetenekler ve Bellek API'leri](#yetenekler-ve-bellek-apileri)
- [Kimlik Doğrulama](#kimlik-doğrulama)
---
## Chat Completions
## Sohbet Tamamlama (Chat Completions)
```bash
POST /v1/chat/completions
@@ -32,32 +46,29 @@ Content-Type: application/json
{
"model": "cc/claude-opus-4-6",
"messages": [
{"role": "user", "content": "Write a function to..."}
{"role": "user", "content": "Python'da bir fonksiyon yaz..."}
],
"stream": true
}
```
### Custom Headers
### Özel Başlıklar
| Header | Direction | Description |
| ------------------------ | --------- | ------------------------------------------------ |
| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
| `X-Session-Id` | Request | Sticky session key for external session affinity |
| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
| `Idempotency-Key` | Request | Dedup key (5s window) |
| `X-Request-Id` | Request | Alternative dedup key |
| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
| Başlık | Yön | Açıklama |
| ------------------------ | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `X-OmniRoute-No-Cache` | İstek | Önbelleği atlamak için `true` ayarlayın |
| `x-omniroute-no-memory` | İstek | Bu istek için bellek ve yetenek enjeksiyonunu atlamak için `true` ayarlayın |
| `X-OmniRoute-Progress` | İstek | İlerleme olayları için `true` ayarlayın |
| `X-Session-Id` | İstek | Harici oturum yakınlığı için yapışkan oturum anahtarı |
| `Idempotency-Key` | İstek | Tekilleştirme anahtarı (5 saniyelik pencere) |
| `X-OmniRoute-Cache` | Yanıt | `HIT` veya `MISS` (akışsız modda) |
| `X-OmniRoute-Idempotent` | Yanıt | İstek tekilleştirilmişse `true` |
| `X-OmniRoute-Version` | Yanıt | OmniRoute derleme sürümü (her zaman bulunur) |
| `X-OmniRoute-Decision` | Yanıt | Yönlendirme izi: `strategy=<ad>; provider=<alias>; latency_ms=<n>` |
---
## Embeddings
## Gömme (Embeddings)
```bash
POST /v1/embeddings
@@ -65,21 +76,14 @@ Authorization: Bearer your-api-key
Content-Type: application/json
{
"model": "nebius/Qwen/Qwen3-Embedding-8B",
"input": "The food was delicious"
"model": "text-embedding-3-small",
"input": "Vektör haline getirilecek metin"
}
```
Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA, **OpenRouter**, **GitHub Models**.
```bash
# List all embedding models
GET /v1/embeddings
```
---
## Image Generation
## Görsel Üretimi (Image Generation)
```bash
POST /v1/images/generations
@@ -87,383 +91,33 @@ Authorization: Bearer your-api-key
Content-Type: application/json
{
"model": "openai/gpt-image-2",
"prompt": "A beautiful sunset over mountains",
"prompt": "Güneş batarken fütüristik bir şehir",
"n": 1,
"size": "1024x1024"
}
```
Available providers: OpenAI (GPT Image 2), xAI (Grok Image), Together AI (FLUX), Fireworks AI, Nebius (FLUX), Hyperbolic, NanoBanana, **OpenRouter**, SD WebUI (local), ComfyUI (local).
```bash
# List all image models
GET /v1/images/generations
```
---
## List Models
## Arama API'si (Search API)
```bash
GET /v1/models
POST /v1/search
Authorization: Bearer your-api-key
→ Returns all chat, embedding, and image models + combos in OpenAI format
```
---
## Compatibility Endpoints
| Method | Path | Format |
| ------ | --------------------------- | ---------------------- |
| POST | `/v1/chat/completions` | OpenAI |
| POST | `/v1/messages` | Anthropic |
| POST | `/v1/responses` | OpenAI Responses |
| POST | `/v1/embeddings` | OpenAI |
| POST | `/v1/images/generations` | OpenAI |
| GET | `/v1/models` | OpenAI |
| POST | `/v1/messages/count_tokens` | Anthropic |
| GET | `/v1beta/models` | Gemini |
| POST | `/v1beta/models/{...path}` | Gemini generateContent |
| POST | `/v1/api/chat` | Ollama |
### Dedicated Provider Routes
```bash
POST /v1/providers/{provider}/chat/completions
POST /v1/providers/{provider}/embeddings
POST /v1/providers/{provider}/images/generations
```
The provider prefix is auto-added if missing. Mismatched models return `400`.
---
## Semantic Cache
```bash
# Get cache stats
GET /api/cache/stats
# Clear all caches
DELETE /api/cache/stats
```
Response example:
```json
{
"semanticCache": {
"memorySize": 42,
"memoryMaxSize": 500,
"dbSize": 128,
"hitRate": 0.65
},
"idempotency": {
"activeKeys": 3,
"windowMs": 5000
}
}
```
---
## Dashboard & Management
### Authentication
| Endpoint | Method | Description |
| ----------------------------- | ------- | --------------------- |
| `/api/auth/login` | POST | Login |
| `/api/auth/logout` | POST | Logout |
| `/api/settings/require-login` | GET/PUT | Toggle login required |
### 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/PATCH/DELETE | Custom models (add, update, hide/show, delete) |
### OAuth Flows
| Endpoint | Method | Description |
| -------------------------------- | ------- | ----------------------- |
| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
### Routing & Config
| Endpoint | Method | Description |
| --------------------- | -------- | ----------------------------- |
| `/api/models/alias` | GET/POST | Model aliases |
| `/api/models/catalog` | GET | All models by provider + type |
| `/api/combos*` | Various | Combo management |
| `/api/keys*` | Various | API key management |
| `/api/pricing` | GET | Model pricing |
### Usage & Analytics
| Endpoint | Method | Description |
| --------------------------- | ------ | -------------------- |
| `/api/usage/history` | GET | Usage history |
| `/api/usage/logs` | GET | Usage logs |
| `/api/usage/request-logs` | GET | Request-level logs |
| `/api/usage/[connectionId]` | GET | Per-connection usage |
### Settings
| Endpoint | Method | Description |
| ------------------------------- | ------------- | ---------------------- |
| `/api/settings` | GET/PUT/PATCH | General settings |
| `/api/settings/proxy` | GET/PUT | Network proxy config |
| `/api/settings/proxy/test` | POST | Test proxy connection |
| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
### Monitoring
| Endpoint | Method | Description |
| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
| `/api/sessions` | GET | Active session tracking |
| `/api/rate-limits` | GET | Per-account rate limits |
| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
### Backup & Export/Import
| Endpoint | Method | Description |
| --------------------------- | ------ | --------------------------------------- |
| `/api/db-backups` | GET | List available backups |
| `/api/db-backups` | PUT | Create a manual backup |
| `/api/db-backups` | POST | Restore from a specific backup |
| `/api/db-backups/export` | GET | Download database as .sqlite file |
| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
### Cloud Sync
| Endpoint | Method | Description |
| ---------------------- | ------- | --------------------- |
| `/api/sync/cloud` | Various | Cloud sync operations |
| `/api/sync/initialize` | POST | Initialize sync |
| `/api/cloud/*` | Various | Cloud management |
### Tunnels
| Endpoint | Method | Description |
| -------------------------- | ------ | ----------------------------------------------------------------------- |
| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
### CLI Tools
| Endpoint | Method | Description |
| ---------------------------------- | ------ | ------------------- |
| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
### ACP Agents
| Endpoint | Method | Description |
| ----------------- | ------ | -------------------------------------------------------- |
| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
### Resilience & Rate Limits
| Endpoint | Method | Description |
| ----------------------- | --------- | ---------------------------------------------------------------------------------- |
| `/api/resilience` | GET/PATCH | Get/update request queue, connection cooldown, provider breaker, and wait settings |
| `/api/resilience/reset` | POST | Reset provider circuit breakers |
| `/api/rate-limits` | GET | Per-account rate limit status |
| `/api/rate-limit` | GET | Global rate limit configuration |
### Evals
| Endpoint | Method | Description |
| ------------ | -------- | --------------------------------- |
| `/api/evals` | GET/POST | List eval suites / run evaluation |
### Policies
| Endpoint | Method | Description |
| --------------- | --------------- | ----------------------- |
| `/api/policies` | GET/POST/DELETE | Manage routing policies |
### Compliance
| Endpoint | Method | Description |
| --------------------------- | ------ | ----------------------------- |
| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
### v1beta (Gemini-Compatible)
| Endpoint | Method | Description |
| -------------------------- | ------ | --------------------------------- |
| `/v1beta/models` | GET | List models in Gemini format |
| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
### Internal / System APIs
| Endpoint | Method | Description |
| ------------------------ | ------ | ---------------------------------------------------- |
| `/api/init` | GET | Application initialization check (used on first run) |
| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
| `/api/restart` | POST | Trigger graceful server restart |
| `/api/shutdown` | POST | Trigger graceful server shutdown |
| `/api/system/env/repair` | POST | Repair OAuth provider environment variables |
| `/api/system-info` | GET | Generate system diagnostics report |
> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
### OAuth Environment Repair _(v3.6.1+)_
```bash
POST /api/system/env/repair
Content-Type: application/json
{
"provider": "claude-code"
}
```
Repairs missing or corrupted OAuth environment variables for a specific provider. Returns:
```json
{
"success": true,
"repaired": ["CLAUDE_CODE_OAUTH_CLIENT_ID", "CLAUDE_CODE_OAUTH_CLIENT_SECRET"],
"backupPath": "/home/user/.omniroute/backups/env-repair-2026-04-11.bak"
"query": "OmniRoute AI gateway nedir?",
"provider": "perplexity"
}
```
---
## Audio Transcription
## Uyumluluk Uç Noktaları
```bash
POST /v1/audio/transcriptions
Authorization: Bearer your-api-key
Content-Type: multipart/form-data
```
Transcribe audio files using Deepgram or AssemblyAI.
**Request:**
```bash
curl -X POST http://localhost:20128/v1/audio/transcriptions \
-H "Authorization: Bearer your-api-key" \
-F "file=@recording.mp3" \
-F "model=deepgram/nova-3"
```
**Response:**
```json
{
"text": "Hello, this is the transcribed audio content.",
"task": "transcribe",
"language": "en",
"duration": 12.5
}
```
**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
---
## Ollama Compatibility
For clients that use Ollama's API format:
```bash
# Chat endpoint (Ollama format)
POST /v1/api/chat
# Model listing (Ollama format)
GET /api/tags
```
Requests are automatically translated between Ollama and internal formats.
---
## Telemetry
```bash
# Get latency telemetry summary (p50/p95/p99 per provider)
GET /api/telemetry/summary
```
**Response:**
```json
{
"providers": {
"claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
"github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
}
}
```
---
## Budget
```bash
# Get budget status for all API keys
GET /api/usage/budget
# Set or update a budget
POST /api/usage/budget
Content-Type: application/json
{
"keyId": "key-123",
"limit": 50.00,
"period": "monthly"
}
```
## Request Processing
1. Client sends request to `/v1/*`
2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
3. Model is resolved (direct provider/model or alias/combo)
4. Credentials selected from local DB with account availability filtering
5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
6. Provider executor sends upstream request
7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
8. Usage/logging recorded
9. Fallback applies on errors according to combo rules
Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
---
## Authentication
- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
- `requireLogin` toggleable via `/api/settings/require-login`
- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
- **OpenAI Responses:** `POST /v1/responses`
- **Anthropic Messages:** `POST /v1/messages`
- **Gemini Native:** `POST /v1beta/models/{model}:generateContent`
- **Ollama Chat:** `POST /v1/api/chat`
- **Token Sayımı:** `POST /v1/messages/count_tokens`

View File

@@ -1,63 +1,50 @@
# CLI-TOOLS (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../reference/CLI-TOOLS.md) · 🇸🇦 [ar](../../../ar/docs/reference/CLI-TOOLS.md) · 🇦🇿 [az](../../../az/docs/reference/CLI-TOOLS.md) · 🇧🇬 [bg](../../../bg/docs/reference/CLI-TOOLS.md) · 🇧🇩 [bn](../../../bn/docs/reference/CLI-TOOLS.md) · 🇨🇿 [cs](../../../cs/docs/reference/CLI-TOOLS.md) · 🇩🇰 [da](../../../da/docs/reference/CLI-TOOLS.md) · 🇩🇪 [de](../../../de/docs/reference/CLI-TOOLS.md) · 🇪🇸 [es](../../../es/docs/reference/CLI-TOOLS.md) · 🇮🇷 [fa](../../../fa/docs/reference/CLI-TOOLS.md) · 🇫🇮 [fi](../../../fi/docs/reference/CLI-TOOLS.md) · 🇫🇷 [fr](../../../fr/docs/reference/CLI-TOOLS.md) · 🇮🇳 [gu](../../../gu/docs/reference/CLI-TOOLS.md) · 🇮🇱 [he](../../../he/docs/reference/CLI-TOOLS.md) · 🇮🇳 [hi](../../../hi/docs/reference/CLI-TOOLS.md) · 🇭🇺 [hu](../../../hu/docs/reference/CLI-TOOLS.md) · 🇮🇩 [id](../../../id/docs/reference/CLI-TOOLS.md) · 🇮🇩 [in](../../../in/docs/reference/CLI-TOOLS.md) · 🇮🇹 [it](../../../it/docs/reference/CLI-TOOLS.md) · 🇯🇵 [ja](../../../ja/docs/reference/CLI-TOOLS.md) · 🇰🇷 [ko](../../../ko/docs/reference/CLI-TOOLS.md) · 🇮🇳 [mr](../../../mr/docs/reference/CLI-TOOLS.md) · 🇲🇾 [ms](../../../ms/docs/reference/CLI-TOOLS.md) · 🇳🇱 [nl](../../../nl/docs/reference/CLI-TOOLS.md) · 🇳🇴 [no](../../../no/docs/reference/CLI-TOOLS.md) · 🇵🇭 [phi](../../../phi/docs/reference/CLI-TOOLS.md) · 🇵🇱 [pl](../../../pl/docs/reference/CLI-TOOLS.md) · 🇵🇹 [pt](../../../pt/docs/reference/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/reference/CLI-TOOLS.md) · 🇷🇴 [ro](../../../ro/docs/reference/CLI-TOOLS.md) · 🇷🇺 [ru](../../../ru/docs/reference/CLI-TOOLS.md) · 🇸🇰 [sk](../../../sk/docs/reference/CLI-TOOLS.md) · 🇸🇪 [sv](../../../sv/docs/reference/CLI-TOOLS.md) · 🇰🇪 [sw](../../../sw/docs/reference/CLI-TOOLS.md) · 🇮🇳 [ta](../../../ta/docs/reference/CLI-TOOLS.md) · 🇮🇳 [te](../../../te/docs/reference/CLI-TOOLS.md) · 🇹🇭 [th](../../../th/docs/reference/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/reference/CLI-TOOLS.md) · 🇵🇰 [ur](../../../ur/docs/reference/CLI-TOOLS.md) · 🇻🇳 [vi](../../../vi/docs/reference/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/reference/CLI-TOOLS.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/reference/CLI-TOOLS.md)
---
---
title: "CLI Araçları — OmniRoute"
version: 3.8.50
lastUpdated: 2026-08-18
lastUpdated: 2026-08-23
---
# CLI Araçları — OmniRoute
# CLI Araçları — OmniRoute (Türkçe)
Son güncelleme: 2026-08-18
OmniRoute, üç özel kontrol paneli sayfasında dağıtılmış üç kategori CLI aracı ile entegre olur:
| Sayfa | Rota | Kavram | Sayı |
| ---------------- | ----------------------- | ------------------------------------------------------------------------------------- | --------------------- |
| **CLI Kodu** | `/dashboard/cli-code` | OmniRoute'a yönlendirdiğiniz kodlama araçları (Müşteri → CLI → OmniRoute → Sağlayıcı) | 26 |
| **CLI Ajanları** | `/dashboard/cli-agents` | OmniRoute'a yönlendirdiğiniz otonom ajanlar (aynı akış, daha geniş kapsam) | 8 |
| **ACP Ajanları** | `/dashboard/acp-agents` | OmniRoute'un stdio/ACP aracılığıyla arka planda oluşturduğu CLIs (ters akış) | kayıt defterine bakın |
Eski rotalar 308 ile yönlendirilir: `/dashboard/cli-tools``/dashboard/cli-code`, `/dashboard/agents``/dashboard/acp-agents`.
🌐 **Languages:** 🇺🇸 [English](../../../../docs/reference/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/reference/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/reference/CLI-TOOLS.md) · 🇧🇩 [bn](../../bn/docs/reference/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/reference/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/reference/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/reference/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/reference/CLI-TOOLS.md) · 🇮🇷 [fa](../../fa/docs/reference/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/reference/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/reference/CLI-TOOLS.md) · 🇮🇳 [gu](../../gu/docs/reference/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/reference/CLI-TOOLS.md) · 🇮🇳 [hi](../../hi/docs/reference/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/reference/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/reference/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/reference/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/reference/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/reference/CLI-TOOLS.md) · 🇮🇳 [mr](../../mr/docs/reference/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/reference/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/reference/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/reference/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/reference/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/reference/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/reference/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/reference/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/reference/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/reference/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/reference/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/reference/CLI-TOOLS.md) · 🇰🇪 [sw](../../sw/docs/reference/CLI-TOOLS.md) · 🇮🇳 [ta](../../ta/docs/reference/CLI-TOOLS.md) · 🇮🇳 [te](../../te/docs/reference/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/reference/CLI-TOOLS.md) · 🇹🇷 [tr](../../tr/docs/reference/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/reference/CLI-TOOLS.md) · 🇵🇰 [ur](../../ur/docs/reference/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/reference/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/reference/CLI-TOOLS.md)
---
## Nasıl Çalışır
OmniRoute, üç özel pano sayfasına yayılmış üç CLI araçları kategorisiyle entegre olur:
| Sayfa | Rota | Konsept | Sayı |
| -------------- | ----------------------- | -------------------------------------------------------------------------- | ------------ |
| **CLI Code's** | `/dashboard/cli-code` | OmniRoute'a yönlendirdiğiniz kodlama araçları (İstemci → CLI → OmniRoute → Sağlayıcı) | 26 |
| **CLI Ajanları**| `/dashboard/cli-agents` | OmniRoute'a yönlendirdiğiniz özerk ajanlar (aynı akış, daha geniş kapsam) | 8 |
| **ACP Ajanları**| `/dashboard/acp-agents` | OmniRoute'un stdio/ACP ile başlattığı CLI'lar (ters başlatma akışı) | bkz. kayıt |
---
## Nasıl Çalışır?
```
CLI Kodu / CLI Ajanları (tüketim akışı):
Claude / Codex / OpenCode / Cline / KiloCode / Continue / Hermes Ajanı / Goose / ...
CLI Araçları (Tüketim Akışı):
Claude / Codex / OpenCode / Cline / KiloCode / Continue / Hermes / Goose / ...
▼ (hepsi OmniRoute'a yönlendirir)
http://YOUR_SERVER:20128/v1
▼ (hepsi OmniRoute'a yönlendirilir)
http://SUNUCUNUZ:20128/v1
▼ (OmniRoute doğru sağlayıcıya yönlendirir)
Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
ACP Ajanları (ters oluşturma akışı):
Müşteri isteği → OmniRoute → stdio/ACP aracılığıyla CLI oluşturur → yanıt
```
**Faydalar:**
**Avantajlar:**
- Tüm araçları yönetmek için tek bir API anahtarı
- Kontrol panelindeki tüm CLIs arasında maliyet takibi
- Her aracı yeniden yapılandırmadan model değiştirme
- Yerel ve uzaktan sunucularda (VPS, Docker, Akamai, Cloudflare Tüneli) çalışır
- Panoda tüm CLI'lar genelinde maliyet takibi
- Her aracı yeniden yapılandırmadan anında model değiştirme
- Yerel ortamda ve uzak sunucularda (VPS, Docker, Cloudflare Tunnel) sorunsuz çalışma
---
## `setup-*` ile Otomatik Yapılandırma
Her aracın yapılandırmasını elle yazmak zorunda değilsiniz. OmniRoute, çalışan bir
OmniRoute'tan (yerel veya uzaktan) **canlı** model kataloğunu okuyan ve aracın kendi
yapılandırmasını makinenize yazan her desteklenen CLI için bir `setup-*`
komutu gönderir:
Her aracın yapılandırmasını elle yazmanıza gerek yoktur:
```bash
omniroute setup-codex omniroute setup-claude omniroute setup-opencode
@@ -65,687 +52,3 @@ omniroute setup-cline omniroute setup-kilo omniroute setup-contin
omniroute setup-cursor omniroute setup-roo omniroute setup-crush
omniroute setup-goose omniroute setup-qwen omniroute setup-aider
```
Her biri `--remote <url> --api-key <key>` (uzaktaki bir OmniRoute'a karşı yerel bir aracı yapılandırma), `--dry-run` (yazmadan önizleme) ve `--port` alır. Model otomatik keşfi olmayan araçlar (Cline, Kilo, Roo, Goose, Aider, Qwen) `--model <id>` (ve etkileşimsiz çalıştırmalar için `--yes`) alır. Doğru ortamın enjekte edildiği ve hiç yapılandırma yazılmadan bir CLI başlatmak için, genel `omniroute run <target>` başlatıcısını kullanın (claude, codex, aider, goose, opencode, qwen, gemini — hedefler ve takma adlar `bin/cli/cli-manifest.mjs`'den gelir); eski her araç için başlatıcılar `omniroute launch` (Claude Kodu) ve `omniroute launch-codex` (Codex) kullanılmaya devam eder. Gemini CLI yalnızca başlatma içindir: bir `omniroute run` hedefidir ancak `setup-*`/`configure` tarifi yoktur.
> **Tam referans:** her komutun ne yazdığı, her bayrak, yerel ve uzaktan, ve hangi araçların `/v1` son ekine ihtiyaç duyduğuna dair ana tablo **[CLI Entegrasyonları](../guides/CLI-INTEGRATIONS.md)**'nda bulunmaktadır.
### Bir konteyner içinde bunları çalıştırma
OmniRoute konteyneri içinde yürütülen bir `setup-*` komutu, konteynerin kendi evine yazar, bu da hiçbir ana CLI tarafından okunmaz ve konteyner ile birlikte kaybolur. OmniRoute bunu algılar ve yazmak yerine talimatlarla `2` ile çıkar. İki desteklenen yol — CLI'yi ana makinede kurmak ve konteynere `omniroute connect` yapmak veya yapılandırma dizinlerini bağlamak ve `CLI_CONFIG_HOME` ayarlamaktır (compose `host` profili). Her `setup-*` komutu, ayrıca `omniroute configure` ve `omniroute config set`, konteynerin kendi CLIs'ini yapılandırmanın gerçekten ne anlama geldiği durumunda `--allow-container-write` alır; `OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE=true` sunucu için aynı şeyi yapar. Bakınız
[Docker Kılavuzu → Ana CLI araçlarını yapılandırma](../guides/DOCKER_GUIDE.md#configuring-host-cli-tools-when-omniroute-runs-in-docker).
Kontrol panelinin **uygulama uç noktası** (`POST /api/cli-tools/apply`) aynı korumayı uygular: bir konteynerde, hedefi ana makineden bağlanmamış bir yazma işlemi **`422`** ile `containerEphemeralTarget: true` yanıtını verir, güvenli hata metni ve — ana makine tarifi olan araçlar için (claude, codex, opencode, cline, kilo, continue) — ana makinede çalıştırılacak bir `hostSetupCommand` (örneğin `omniroute setup-opencode`); hiçbir şey yazılmaz. `dryRun: true` konteyner modunda çalışmaya devam eder ve diskle temas etmeden üretilen içeriği + hedef yolunu döndürür, böylece kontrol panelinden önizleme yapabilir ve ana makinede uygulayabilirsiniz. Bu davranış kasıtlıdır ve `tests/unit/api/cli-tools/apply-container-guard.test.ts` ile geriye dönük olarak korunmaktadır — asla bir 422'yi korumayı kaldırarak "düzeltmeyin".
---
## Gerçek Kaynağı
Birleşik katalog `src/shared/constants/cliTools.ts` içinde `CLI_TOOLS: Record<string, CliCatalogEntry>` olarak yer almaktadır.
Her bir girişin bu alanları vardır (tanımlı `src/shared/schemas/cliCatalog.ts` içinde):
| Alan | Tür | Açıklama |
| ----------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------ |
| `category` | `"code" \| "agent"` | Araç hangi sayfada görünür |
| `vendor` | `string` | Araç kaynağı ("Anthropic", "OSS (P. Gauthier)") |
| `acpSpawnable` | `boolean` | ACP Ajanı olarak da kullanılabilir (rozet gösterilir) |
| `baseUrlSupport` | `"full" \| "partial" \| "none"` | Özel uç nokta destek seviyesi. `"none"` = MITM backlog |
| `configType` | `"env" \| "custom" \| "guide" \| "custom-builder" \| "mitm"` | Yapılandırma mekanizması |
| `id`, `name`, `color`, `description`, `docsUrl` | standart | Temel görüntüleme alanları |
`baseUrlSupport: "none"` olan girişler, gösterim sayfalarında **gösterilmez** — bunlar plan 11 için MITM backlog'unda kaydedilmiştir (bkz. `_tasks/features-v3.8.6/refactorpages/_orchestration/_plan11-mitm-backlog.md`).
### Yetenek katmanları (kataloglu × tespit edilebilir × yapılandırılabilir × başlatılabilir)
Her kataloglu araç tespit edilebilir, yapılandırılabilir veya başlatılabilir değildir. Her katmanın bir
belirleyici kaynağı vardır ve bir drift testi bunları uyumlu tutar:
| Katman | Anlamı | Belirtilen |
| ---------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------ |
| **Kataloglu** | Gösterim katalogunda görünür (isim, satıcı, belgeler, yapılandırma türü) | `src/shared/constants/cliTools.ts` (`CLI_TOOLS`) |
| **Tespit Edilebilir** | İkili/yapılandırma tespiti, sağlık kontrolleri, yapılandırma yolları | `src/shared/services/cliRuntime.ts` (`CLI_TOOLS` çalışma kataloğu) |
| **Yapılandırılabilir** | `omniroute configure <cli>` tarafından desteklenir (kurulum tarifi mevcut) | `bin/cli/cli-manifest.mjs` (`configure: true`) |
| **Başlatılabilir** | `omniroute run <target>` tarafından desteklenir (env/args enjeksiyonu tanımlı) | `bin/cli/cli-manifest.mjs` (`run: true`) |
`bin/cli/cli-manifest.mjs`, CLI komut yüzeyleri için kanonik yürütülebilir manifestodur: `run`, `configure` ve shell-tamamlayıcı jeneratörleri tüm hedef listelerini, takma ad çözümlemelerini (örneğin `kilocode`/`kilo-code`/`kilo_cli``kilo`) ve `--model` bayrağı bağlantılarını buradan alır. Drift koruma
`tests/unit/cli/cli-manifest-drift.test.ts`, manifestonun, çalışma
kataloğunun, UI kataloğunun ve her tüketici yüzeyinin senkron kalmasını sağlar — bir yüzeye eklenen bir hedef, diğerleri olmadan eklenirse, sessizce drift etmek yerine test grubunu başarısız kılar.
## 1. CLI Kod Kataloğu (26 araç)
`/dashboard/cli-code` içinde yer alan tüm araçlar. `baseUrlSupport: none` olanlar, özel bir temel URL yerine MITM veya manuel bir kılavuz aracılığıyla bağlanmıştır:
| id | isim | satıcı | baseUrlSupport | configType | acpSpawnable |
| ------------ | ------------------------- | ----------------------------- | -------------- | -------------- | ------------ |
| claude | Claude Kodu | Anthropic | full | env | true |
| codex | OpenAI Codex CLI | OpenAI | full | custom | true |
| zcode | ZCode (GLM Kodlama Planı) | Z.ai | none | custom | false |
| cline | Cline | OSS (eski-Claude Geliştirici) | full | custom | true |
| kilo | Kilo Kodu | Kilo-Org | full | custom | false |
| roo | Roo Kodu | Roo (OSS) | full | guide | false |
| continue | Devam Et | continue.dev | full | guide | false |
| aider | Aider | OSS (P. Gauthier) | full | guide | true |
| forge | ForgeCode | Antinomy HQ | full | custom | true |
| jcode | jcode | 1jehuang (OSS) | full | custom | false |
| deepseek-tui | DeepSeek TUI | Hunter Bown (OSS) | full | custom | false |
| codewhale | CodeWhale | Hmbown (OSS) | full | custom | false |
| opencode | OpenCode | Anomaly (eski-SST) | full | guide | true |
| droid | Factory Droid | Factory AI | partial | guide | false |
| copilot | GitHub Copilot CLI | GitHub/MS | full | custom | false |
| cursor-cli | Cursor CLI | Anysphere | partial | guide | true |
| smelt | Smelt | leonardcser (OSS) | full | custom | false |
| pi | Pi (pi-coding-agent) | M. Zechner (OSS) | full | custom | false |
| grok-build | Grok Build | xAI | full | custom | false |
| crush | Crush | OSS (Charm) | full | custom | false |
| qwen | Qwen Kodu | Alibaba | full | guide | true |
| cursor | Cursor | Anysphere | none | guide | false |
| antigravity | Antigravity | Google | none | mitm | false |
| hermes | Hermes | Nous Research | none | guide | false |
| kiro | Kiro AI | Amazon | none | mitm | false |
| custom | Özel CLI | — | full | custom-builder | false |
`baseUrlSupport: "partial"` olan araçlar, gösterge paneli kartında "⚠ Temel URL kısmi" rozetini gösterir.
## 2. CLI Ajanları Kataloğu (8 araç)
`/dashboard/cli-agents` içinde görünen otonom ajanlar:
| id | isim | satıcı | baseUrlDestek | acpSpawnable |
| ------------ | ---------------- | ------------------------ | ------------- | ------------ |
| hermes-agent | Hermes Ajanı | Nous Research | tam | false |
| openclaw | OpenClaw | OSS (P. Steinberger) | tam | true |
| goose | Goose | Block / Linux Foundation | tam | true |
| interpreter | Open Interpreter | OSS | tam | true |
| warp | Warp AI | Warp Inc. | kısmi | true |
| agent-deck | Ajan Destesi | asheshgoplani (OSS) | tam | false |
| omp | Oh My Pi | OSS | tam | true |
| letta | Letta CLI | Letta | tam | false |
---
## 3. ACP Ajanları (/dashboard/acp-agents)
Bu sayfa (`/dashboard/agents`'dan yeniden adlandırılmıştır) OmniRoute'un stdio/ACP protokolü aracılığıyla **oluşturabileceği** arka uç yürütme motorlarını gösterir. Katalog, `src/lib/acp/registry.ts` içinde ayrı olarak korunmaktadır ve `CLI_TOOLS` ile **aynı değildir**.
---
## 4. MITM Bekleme Listesi (dashboard'da gösterilmez)
Aşağıdaki CLIs yerel olarak özel bir temel URL'yi desteklememektedir ve CLI Kodu veya CLI Ajanları sayfalarında **listelenmemiştir**. Plan 11'de MITM müdahalesi için adaylardır:
| CLI | Sebep |
| ------------------- | -------------------------------------------------- |
| windsurf | BYOK, seçili Claude modelleri + kurumsal URL/token |
| amp | Kapalı ekosistem (Sourcegraph) |
| amazon-q / kiro-cli | AWS SSO kimlik doğrulama, özel URL yok |
| cowork | Anthropic Desktop, yapılandırılabilir uç nokta yok |
Tam çapraz referans için `_tasks/features-v3.8.6/refactorpages/_orchestration/_plan11-mitm-backlog.md`'ye bakın.
---
## 5. Batch Tespit API'si
Tüm araç tespiti tek bir uç nokta üzerinden toplanmaktadır:
**`GET /api/cli-tools/all-statuses`**
- Yetki: `requireCliToolsAuth(request)` (diğer `/api/cli-tools/` yollarıyla aynı)
- Döner: `Record<toolId, ToolBatchStatus>` (tip: `src/shared/types/cliBatchStatus.ts`)
- Strateji: Tüm araçlar üzerinde `Promise.all`, her araç için 5s zaman aşımı
- Önbellek: yapılandırma dosyası `mtime` ile indekslenmiş bellek içi LRU. mtime değiştiğinde önbellek geçersiz kılınır. Sunucu yeniden başlatıldığında sıfırlanır.
Araç başına yanıt şekli:
```ts
interface ToolBatchStatus {
detection: {
installed: boolean;
runnable: boolean;
version?: string;
command?: string;
commandPath?: string;
reason?: string;
};
config: {
status: "configured" | "not_configured" | "not_installed" | "unknown" | "other";
endpoint?: string | null;
lastConfiguredAt?: string | null;
};
error?: string; // temizlenmiş, yığın izleri yok
}
```
## 6. Yeni Araçlar için Ayar İşleyicileri
`configType: "custom"` olan yeni araçların özel ayar API yolları vardır:
| Yol | Araç |
| ------------------------------------------- | -------------------------------------------------------------------------- |
| `POST /api/cli-tools/forge-settings` | ForgeCode (.forge.toml) |
| `POST /api/cli-tools/jcode-settings` | jcode (--base-url bayrağı) |
| `POST /api/cli-tools/deepseek-tui-settings` | DeepSeek TUI (OPENAI_BASE_URL, eski) |
| `POST /api/cli-tools/codewhale-settings` | CodeWhale (OPENAI_BASE_URL, birincil + eski `~/.deepseek` senkronizasyonu) |
| `POST /api/cli-tools/smelt-settings` | Smelt |
| `POST /api/cli-tools/pi-settings` | Pi kodlama aracı |
| `POST /api/cli-tools/grok-build-settings` | Grok Build (~/.grok/config.toml, `[model.omniroute]`) |
| `POST /api/cli-tools/qwen-settings` | Qwen Code (`~/.qwen/settings.json` + özel `.env` anahtarı) |
Tüm yollar hata yanıtları için `sanitizeErrorMessage()` kullanır (Sert Kural #12).
---
## 7. Gösterge Paneli Sayfaları Mimarisi
### CLI Kodu (`/dashboard/cli-code`)
- `src/app/(dashboard)/dashboard/cli-code/page.tsx` — sunucu bileşeni
- `src/app/(dashboard)/dashboard/cli-code/CliCodePageClient.tsx` — istemci ızgarası
- `src/app/(dashboard)/dashboard/cli-code/[id]/page.tsx` — araç detay sayfası
- `src/app/(dashboard)/dashboard/cli-code/components/` — 12 özel araç kartı + `ToolDetailClient.tsx`
### CLI Ajanları (`/dashboard/cli-agents`)
- `src/app/(dashboard)/dashboard/cli-agents/page.tsx` — sunucu bileşeni
- `src/app/(dashboard)/dashboard/cli-agents/CliAgentsPageClient.tsx` — istemci ızgarası
- `src/app/(dashboard)/dashboard/cli-agents/[id]/page.tsx``ToolDetailClient`'i yeniden kullanır
### ACP Ajanları (`/dashboard/acp-agents`)
- `src/app/(dashboard)/dashboard/acp-agents/page.tsx` — sunucu bileşeni ( `agents/`'dan taşındı)
### Paylaşılan UI Bileşenleri (`src/shared/components/cli/`)
| Dosya | Amaç |
| ----------------------- | ----------------------------------------------------- |
| `CliToolCard.tsx` | Akıllı durum kartı (tespit + yapılandırma + uç nokta) |
| `CliConceptCard.tsx` | Sayfa başına kavram açıklama kartı |
| `CliComparisonCard.tsx` | CLI türleri arasında üç sütunlu karşılaştırma |
| `BaseUrlSelect.tsx` | Uç nokta açılır menüsü (Yerel/Bulut/Özel) |
| `ApiKeySelect.tsx` | API anahtarı seçici |
| `ManualConfigModal.tsx` | Kopyalanabilir yapılandırma kesiti modali |
### Paylaşılan Hook (`src/shared/hooks/cli/`)
| Dosya | Amaç |
| ------------------------- | ----------------------------------------------------------------------- |
| `useToolBatchStatuses.ts` | `/api/cli-tools/all-statuses`'i alır, yükleme/yenileme durumunu yönetir |
## 8. i18n
Plan 14 F9'da eklenen yeni ad alanları:
| Ad Alanı | Amaç |
| ----------- | --------------------------------------------------------------------------------------- |
| `cliCommon` | Paylaşılan metinler (kart etiketleri, kavram/kıyas metinleri, detay sayfası etiketleri) |
| `cliCode` | CLI Kodu sayfası metinleri |
| `cliAgents` | CLI Ajanları sayfası metinleri |
| `acpAgents` | ACP Ajanları sayfası metinleri |
Tam PT-BR ve EN çevirileri sağlanmıştır. 39 diğer yerel ayar, `src/i18n/request.ts` içindeki ad alanı düzeyinde birleştirme ile otomatik olarak EN'ye geri döner.
---
## 9. Hızlı Başlangıç
### Adım 1 — OmniRoute API Anahtarı Alın
1. `/dashboard/api-manager`'ıın → **API Anahtarı Oluştur**
2. Bir isim verin (örn. `cli-tools`) ve tüm izinleri seçin
3. Anahtarı kopyalayın — aşağıdaki her CLI için buna ihtiyacınız olacak
> Anahtarınız şöyle görünecek: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
---
### Adım 2 — CLI Araçlarını Yükleyin
Tüm npm tabanlı araçlar Node.js 22.22.2+ veya 24.x gerektirir:
```bash
# Claude Code (Anthropic)
npm install -g @anthropic-ai/claude-code
# OpenAI Codex
npm install -g @openai/codex
# OpenCode
npm install -g opencode-ai
# Cline
npm install -g cline
# KiloCode
npm install -g kilocode
# Qwen Code
npm install -g @qwen-code/qwen-code
# Google Gemini CLI (launchable via `omniroute run gemini` → /v1beta surface)
npm install -g @google/gemini-cli
# Aider
pip install aider-chat
# Smelt
cargo install smelt # Rust tabanlı
# Pi coding agent
# yükleme için https://github.com/zechnerj/pi-coding-agent adresine bakın
# jcode
# yükleme için https://github.com/1jehuang/jcode adresine bakın
```
---
### Adım 3 — Dashboard Üzerinden Yapılandırın
1. `http://localhost:20128/dashboard/cli-code` adresine gidin
2. Araçlar ızgarasında aracınızı bulun
3. Aracı detay sayfasını açmak için karta tıklayın
4. API anahtarınızı ve temel URL'yi seçin
5. **Yapılandırmayı Uygula**'ya tıklayın veya manuel yapılandırma parçasını kopyalayın
---
### Adım 4 — Küresel Ortam Değişkenlerini Ayarlayın
```bash
# OmniRoute Evrensel Uç Noktası
export OPENAI_BASE_URL="http://localhost:20128/v1"
export OPENAI_API_KEY="sk-your-omniroute-key"
export ANTHROPIC_BASE_URL="http://localhost:20128"
export ANTHROPIC_AUTH_TOKEN="sk-your-omniroute-key"
# Gemini CLI, KÖK'te GOOGLE_GEMINI_BASE_URL okur (SDK'sı /v1beta/... ekler)
export GOOGLE_GEMINI_BASE_URL="http://localhost:20128"
export GEMINI_API_KEY="sk-your-omniroute-key"
```
> **Uzak bir sunucu** için `localhost:20128`'i sunucu IP'si veya alan adı ile değiştirin,
> örn. `http://<your-server-ip>:20128`.
---
### Adım 4 — Her Aracı Yapılandırın
#### Claude Code
```bash
# ~/.claude/settings.json oluşturun:
mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
{
"env": {
"ANTHROPIC_BASE_URL": "http://localhost:20128",
"ANTHROPIC_AUTH_TOKEN": "sk-your-omniroute-key"
}
}
EOF
```
Claude Code için birleşik Anthropic geçiş kökünü kullanın. Burada `/v1` eklemeyin.
**Test:** `claude "merhaba de"`
---
#### OpenAI Codex
Modern Codex (v0.137+) yalnızca `~/.codex/config.toml` dosyasını okur — eski
`config.yaml`, miras npm CLI'ye aittir ve sessizce yok sayılır. API
anahtarı, dosya içinde asla değil, `OMNIROUTE_API_KEY` ortam değişkeninde (`env_key`) kalır:
```bash
mkdir -p ~/.codex && cat > ~/.codex/config.toml << EOF
model_provider = "omniroute"
[model_providers.omniroute]
name = "OmniRoute"
base_url = "http://localhost:20128/v1"
env_key = "OMNIROUTE_API_KEY"
requires_openai_auth = false
EOF
export OMNIROUTE_API_KEY="sk-your-omniroute-key"
```
Tam referans (profiller, `wire_api`, bağlam pencereleri): [CODEX-CLI-CONFIGURATION.md](../guides/CODEX-CLI-CONFIGURATION.md).
**Test:** `codex "2+2 nedir?"`
---
#### OpenCode
```bash
mkdir -p ~/.config/opencode && cat > ~/.config/opencode/opencode.json << EOF
{
"\$schema": "https://opencode.ai/config.json",
"provider": {
"omniroute": {
"npm": "@ai-sdk/openai-compatible",
"name": "OmniRoute",
"options": {
"baseURL": "http://localhost:20128/v1",
"apiKey": "sk-your-omniroute-key"
},
"models": {
"claude-sonnet-4-5": { "name": "claude-sonnet-4-5" },
"claude-sonnet-4-5-thinking": { "name": "claude-sonnet-4-5-thinking" },
"gemini-3-flash": { "name": "gemini-3-flash" }
}
}
}
}
EOF
```
**Test:** `opencode`
> Düşünme varyantlarını göndermek için `opencode run "prompt'iniz" --model omniroute/claude-sonnet-4-5-thinking --variant high` kullanın.
---
#### Cline (CLI veya VS Code)
**CLI modu:**
```bash
mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
{
"apiProvider": "openai",
"openAiBaseUrl": "http://localhost:20128/v1",
"openAiApiKey": "sk-your-omniroute-key"
}
EOF
```
**VS Code modu:**
Cline uzantı ayarları → API Sağlayıcı: `OpenAI Uyumluluğu` → Temel URL: `http://localhost:20128/v1`
Ya da OmniRoute dashboard'unu kullanarak → **CLI Araçları → Cline → Yapılandırmayı Uygula**.
---
#### KiloCode (CLI veya VS Code)
**CLI modu:**
```bash
kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
```
**VS Code ayarları:**
```json
{
"kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
"kilo-code.apiKey": "sk-your-omniroute-key"
}
```
Ya da OmniRoute dashboard'unu kullanarak → **CLI Araçları → KiloCode → Yapılandırmayı Uygula**.
---
#### Continue (VS Code Uzantısı)
`~/.continue/config.yaml` dosyasını düzenleyin:
```yaml
models:
- name: OmniRoute
provider: openai
model: auto
apiBase: http://localhost:20128/v1
apiKey: sk-your-omniroute-key
default: true
```
Düzenledikten sonra VS Code'u yeniden başlatın.
---
#### VS Code Insiders (`chatLanguageModels.json`)
VS Code Insiders, özel uç nokta modelleri için yapılandırıldığında ve OmniRoute'un özel bir başlık alanı olmadan çalışmasını istediğinizde bunu kullanın.
**Tavsiye edilen konum:**
- Linux: `~/.config/Code - Insiders/User/chatLanguageModels.json`
- Windows: `%APPDATA%/Code - Insiders/User/chatLanguageModels.json`
**Tokenize edilmiş OmniRoute takma adını kullanarak örnek:**
```json
[
{
"vendor": "customendpoint",
"id": "auto",
"name": "OmniRoute Auto",
"family": "gpt-4",
"version": "1.0.0",
"url": "http://localhost:20128/api/v1/vscode/sk-your-omniroute-key/chat/completions",
"modelsUrl": "http://localhost:20128/api/v1/vscode/sk-your-omniroute-key/models",
"requestFormat": "openai-chat-completions",
"contextWindow": 256000,
"maxOutputTokens": 32768,
"auth": {
"type": "none"
}
}
]
```
**Notlar:**
- `sk-your-omniroute-key`'i OmniRoute'da oluşturulan bir API anahtarı ile değiştirin.
- `url` alanı `/api/v1/vscode/{token}/chat/completions`'a işaret etmelidir.
- `modelsUrl` alanı `/api/v1/vscode/{token}/models`'a işaret etmelidir.
- İstemci özel başlıkları desteklediğinde normal `/v1` + Bearer başlık akışını tercih edin.
- URL'ye gömülü tokenler, uyumluluk geri dönüşü olarak kullanılmaktadır ve editör günlüklerinde veya proxy geçmişinde görünebilir.
---
#### Kiro CLI (Amazon)
```bash
# AWS/Kiro hesabınıza giriş yapın:
kiro-cli login
# CLI kendi kimlik doğrulamasını kullanır — Kiro CLI için arka uç olarak OmniRoute gerekli değildir.
# Diğer araçlar için OmniRoute ile birlikte kiro-cli kullanın.
kiro-cli status
```
**Kiro IDE** masaüstü uygulaması için, OmniRoute tarafından sağlanan MITM uç noktasını kullanın
`/dashboard/cli-tools → Kiro` altında.
## 10. Dahili OmniRoute CLI
`omniroute` ikili dosyası, sunucu yaşam döngüsü, kurulum, tanılama ve sağlayıcı yönetimi için komutlar sağlar. Giriş noktası: `bin/omniroute.mjs`.
```bash
omniroute # Sunucuyu başlat (varsayılan port 20128)
omniroute setup # Etkileşimli kurulum sihirbazı
omniroute doctor # Yapılandırmayı, DB'yi, portları, çalışma zamanını kontrol et
omniroute providers list # Yapılandırılmış sağlayıcı bağlantıları
omniroute providers test-all # Her aktif bağlantıyı test et
omniroute reset-password # Yönetici şifresini sıfırla
omniroute logs # İstek günlüklerini akıt
omniroute health # Ayrıntılı sağlık durumu (kesiciler, önbellek, bellek)
omniroute --version # Sürümü yazdır
omniroute --help # Tüm komutları göster
```
### Kurulum ve Başlatma
```bash
omniroute setup # Etkileşimli kurulum sihirbazı
omniroute setup --non-interactive # CI/otomasyon modu (çevre değişkenlerini + bayrakları okur)
omniroute setup --password '<value>' # Yönetici şifresini doğrudan ayarla
omniroute setup --add-provider \
--provider openai \
--api-key '<value>' \
--test-provider # Bir sağlayıcıyı ekle ve test et
```
Etkileşimli olmayan kurulum için tanınan çevre değişkenleri:
| Var | Amaç |
| ------------------- | --------------------------------------------------------------------------------- |
| `OMNIROUTE_API_KEY` | Sağlayıcı API anahtarı (Commander `.env()` aracılığıyla `--api-key` ile bağlanır) |
| `DATA_DIR` | OmniRoute veri dizinini geçersiz kıl |
Diğer tüm etkileşimli olmayan girdiler bayraklar olarak geçilir, çevre değişkenleri olarak değil:
`--password`, `--provider`, `--provider-name`, `--provider-base-url`, `--default-model`
(bkz. yukarıdaki `omniroute setup` seçenekleri).
### Tanılama
```bash
omniroute doctor # Yapılandırmayı, DB'yi, portları, çalışma zamanını, belleği, canlılığı kontrol et
omniroute doctor --json # Makine okunabilir JSON
omniroute doctor --no-liveness # HTTP sağlık sorgusunu atla
omniroute doctor --host 0.0.0.0 # Canlılık ana bilgisayarını geçersiz kıl
omniroute doctor --liveness-url <url> # Tam sağlık uç noktası URL'sini geçersiz kıl
```
Doktor bu kontrolleri yapar: `Yapılandırma`, `Veritabanı`, `Depolama/şifreleme`,
`Port kullanılabilirliği`, `Node çalışma zamanı`, `Yerel ikili` (better-sqlite3),
`Bellek` ve `Sunucu canlılığı`. Herhangi bir kontrol `başarısız` olursa sıfırdan farklı bir çıkış yapar.
### Sağlayıcı Yönetimi
```bash
omniroute providers available # OmniRoute sağlayıcı kataloğu
omniroute providers available --search openai # Kataloğu id/ad/alias/kategoriye göre filtrele
omniroute providers available --category api-key # Kategoriye göre filtrele (api-key, oauth, ücretsiz, ...)
omniroute providers available --json # Makine okunabilir JSON
omniroute providers list # Yapılandırılmış sağlayıcı bağlantıları
omniroute providers list --json
omniroute providers test <id|name> # Bir yapılandırılmış bağlantıyı test et
omniroute providers test-all # Her aktif bağlantıyı test et
omniroute providers validate # Yerel yalnızca yapısal doğrulama
omniroute providers add <provider> --credential-env PROVIDER_KEY
omniroute providers import ./providers.json --dry-run --json
omniroute providers auth <provider> # Mevcut OAuth akışı
omniroute providers edit <id|name> --default-model <model>
omniroute providers remove <id|name> --yes
```
`providers add/import/auth/edit/remove` API-first'tır ve bu nedenle
aktif yerel veya uzaktan bağlama karşı çalışır. Kimlik bilgisi girişi
`--credential-stdin` veya `--credential-env` kullanmalıdır; `--dry-run --json` yalnızca
gizlenmiş varlık/şekil raporları. `providers available` OmniRoute kataloğunu okur;
`providers list/test/test-all/validate` yerel SQLite davranışlarını korur ve
sunucunun çalışmasını gerektirmez.
### Kurtarma ve Sıfırlama
```bash
omniroute reset-password # Yönetici şifresini sıfırla (ayrıca: omniroute-reset-password)
omniroute reset-encrypted-columns # Şifreli kimlik bilgisi sıfırlama için uyarı göster + kuru çalışma
omniroute reset-encrypted-columns --force # SQLite'daki şifreli kimlik bilgilerini gerçekten sıfırla
```
### Kimlik Bilgisi Dışa Aktarma (⚠ dikkatli kullanın)
```bash
omniroute auth export # Uyarı göster + onay kapısı — DB erişimi yok
omniroute auth export --force # Tüm bağlantıların ŞİFRESİZ kimlik bilgilerini stdout'a JSON olarak dışa aktar
omniroute auth export --force --id <id> # Sadece eşleşen bağlantıyı dışa aktar
omniroute auth export --force --format env # OMNIROUTE_<PROVIDER>_<FIELD>=<value> satırlarını yayınla
omniroute auth export --force --out creds.json # Bir dosyaya yaz (0600 izinleri ile oluşturulur)
```
`auth export` **yerel yalnızca** (doğrudan SQLite okuma, HTTP rotası yok) ve kasıtlı olarak **düz metin** `apiKey`/`accessToken`/`refreshToken`/`idToken` değerlerini yazdırır/yazar — bu bir özellik, hata değil. Veritabanından hiçbir şey okunmaz ve hiçbir şey şifrelenmez, `--force` olmadan. Herhangi bir düz metin yayımlanmadan önce her zaman bir stderr uyarı bandı yazdırılır. `STORAGE_ENCRYPTION_KEY` ayarlanmış olmalıdır. Şifrelemeyi başaramayan bir alan (eski anahtar, bozuk şifreli metin) `export` işlemini durdurmak veya temel hatayı sızdırmak yerine `"<field>DecryptFailed: true"` olarak rapor edilir.
### Diğer alt komutlar
Bunlar, aksi belirtilmedikçe çalışan bir OmniRoute sunucusu varsayar:
```bash
omniroute status # Kapsamlı çalışma durumu
omniroute logs # İstek günlüklerini akıt (--json, --search, --follow)
omniroute config show # Mevcut yapılandırmayı görüntüle
omniroute provider list # Mevcut sağlayıcıları listele (providers list'in takma adı)
omniroute provider add # OmniRoute'u bir araçta sağlayıcı olarak kaydet
omniroute keys add | list | remove # API anahtarlarını yönet
omniroute models [provider] # Modelleri listele (--json, --search)
omniroute combo list | switch | create | delete
omniroute backup # Yapılandırma + DB anlık görüntüsü
omniroute restore # Önceki bir anlık görüntüden geri yükle
omniroute health # Ayrıntılı sağlık durumu (kesiciler, önbellek, bellek)
omniroute quota # Sağlayıcı kota kullanımı
omniroute cache # Önbellek durumu
omniroute cache clear # Anlamsal + imza önbelleklerini temizle
omniroute mcp status | restart # MCP sunucu durumu / yeniden başlat
omniroute a2a status | card # A2A sunucu durumu / ajan kartı
omniroute tunnel list | create | stop # Tünelleri yönet (cloudflare/tailscale/ngrok)
omniroute env show | get <k> | set <k> <v> # Çevre değişkenlerini denetle / ayarla (geçici)
omniroute test # Sağlayıcı bağlantı testi
omniroute update # Güncellemeleri kontrol et
omniroute completion # Shell tamamlama oluştur
```
### Yaygın bayraklar
| Bayrak | Açıklama |
| ------------------- | --------------------------------------------------------- |
| `--no-open` | Başlangıçta tarayıcıyı otomatik açma |
| `--port <n>` | API portunu geçersiz kıl (varsayılan 20128) |
| `--mcp` | IDE'ler için stdio üzerinden MCP sunucusu olarak çalıştır |
| `--non-interactive` | CI modu (hiçbir istem; çevre/bayraklardan okur) |
| `--json` | Makine okunabilir JSON çıktısı (doctor, providers, vb.) |
| `--help`, `-h` | Komut spesifik yardım göster |
| `--version`, `-v` | Yüklenen sürümü yazdır |
---
## Mevcut API Uç Noktaları
| Uç Nokta | Açıklama | Kullanım Alanı |
| -------------------------- | ---------------------------------- | ------------------------------- |
| `/v1/chat/completions` | Standart sohbet (tüm sağlayıcılar) | Tüm modern araçlar |
| `/v1/responses` | Yanıtlar API'si (OpenAI formatı) | Codex, ajans iş akışları |
| `/v1/completions` | Eski metin tamamlama | `prompt:` kullanan eski araçlar |
| `/v1/embeddings` | Metin gömme | RAG, arama |
| `/v1/images/generations` | Görüntü üretimi | GPT-Image, Flux, vb. |
| `/v1/audio/speech` | Metinden sese | ElevenLabs, OpenAI TTS |
| `/v1/audio/transcriptions` | Sesten metne | Deepgram, AssemblyAI |
Yapıştırmaya hazır örnekler ile token'lı OmniRoute URL'si:
```txt
Token örneği: sk-a3ab3c080beaee3a-69f4a4-070d71af
Standart OpenAI tabanı: http://localhost:20128/v1
VS Code modelleri: http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/models
VS Code sohbeti: http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/chat/completions
VS Code yanıtları: http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/responses
Ollama etiketleri: http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/api/tags
Ollama sohbeti: http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/api/chat
```
---
## Sorun Giderme
| Hata | Sebep | Çözüm |
| ---------------------------------------------------- | ---------------------------------- | ------------------------------------------------- |
| `Connection refused` | OmniRoute çalışmıyor | `omniroute serve` |
| `401 Unauthorized` | Yanlış API anahtarı | `/dashboard/api-manager` içinde kontrol edin |
| `No combo configured` | Aktif yönlendirme kombinasyonu yok | `/dashboard/combos` içinde ayarlayın |
| CLI "not installed" gösteriyor | İkili dosya PATH'te değil | `which <command>` kontrol edin |
| Dashboard kurulumdan sonra "not detected" gösteriyor | Önbellek eski | Dashboard'da "⟳ Tespiti yenile" butonuna tıklayın |
| Eski bağlantı `/dashboard/cli-tools` | Pre-v3.8.6 yer imi | `/dashboard/cli-code` (308) yönlendirilmiştir |
| Eski bağlantı `/dashboard/agents` | Pre-v3.8.6 yer imi | `/dashboard/acp-agents` (308) yönlendirilmiştir |

View File

@@ -1,665 +1,90 @@
# Environment Variables Reference (Türkçe)
---
title: "Ortam Değişkenleri Referansı"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/ENVIRONMENT.md) · 🇸🇦 [ar](../../ar/docs/ENVIRONMENT.md) · 🇧🇬 [bg](../../bg/docs/ENVIRONMENT.md) · 🇧🇩 [bn](../../bn/docs/ENVIRONMENT.md) · 🇨🇿 [cs](../../cs/docs/ENVIRONMENT.md) · 🇩🇰 [da](../../da/docs/ENVIRONMENT.md) · 🇩🇪 [de](../../de/docs/ENVIRONMENT.md) · 🇪🇸 [es](../../es/docs/ENVIRONMENT.md) · 🇮🇷 [fa](../../fa/docs/ENVIRONMENT.md) · 🇫🇮 [fi](../../fi/docs/ENVIRONMENT.md) · 🇫🇷 [fr](../../fr/docs/ENVIRONMENT.md) · 🇮🇳 [gu](../../gu/docs/ENVIRONMENT.md) · 🇮🇱 [he](../../he/docs/ENVIRONMENT.md) · 🇮🇳 [hi](../../hi/docs/ENVIRONMENT.md) · 🇭🇺 [hu](../../hu/docs/ENVIRONMENT.md) · 🇮🇩 [id](../../id/docs/ENVIRONMENT.md) · 🇮🇹 [it](../../it/docs/ENVIRONMENT.md) · 🇯🇵 [ja](../../ja/docs/ENVIRONMENT.md) · 🇰🇷 [ko](../../ko/docs/ENVIRONMENT.md) · 🇮🇳 [mr](../../mr/docs/ENVIRONMENT.md) · 🇲🇾 [ms](../../ms/docs/ENVIRONMENT.md) · 🇳🇱 [nl](../../nl/docs/ENVIRONMENT.md) · 🇳🇴 [no](../../no/docs/ENVIRONMENT.md) · 🇵🇭 [phi](../../phi/docs/ENVIRONMENT.md) · 🇵🇱 [pl](../../pl/docs/ENVIRONMENT.md) · 🇵🇹 [pt](../../pt/docs/ENVIRONMENT.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ENVIRONMENT.md) · 🇷🇴 [ro](../../ro/docs/ENVIRONMENT.md) · 🇷🇺 [ru](../../ru/docs/ENVIRONMENT.md) · 🇸🇰 [sk](../../sk/docs/ENVIRONMENT.md) · 🇸🇪 [sv](../../sv/docs/ENVIRONMENT.md) · 🇰🇪 [sw](../../sw/docs/ENVIRONMENT.md) · 🇮🇳 [ta](../../ta/docs/ENVIRONMENT.md) · 🇮🇳 [te](../../te/docs/ENVIRONMENT.md) · 🇹🇭 [th](../../th/docs/ENVIRONMENT.md) · 🇹🇷 [tr](../../tr/docs/ENVIRONMENT.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ENVIRONMENT.md) · 🇵🇰 [ur](../../ur/docs/ENVIRONMENT.md) · 🇻🇳 [vi](../../vi/docs/ENVIRONMENT.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ENVIRONMENT.md)
# Ortam Değişkenleri Referansı (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/reference/ENVIRONMENT.md) · 🇸🇦 [ar](../../ar/docs/reference/ENVIRONMENT.md) · 🇧🇬 [bg](../../bg/docs/reference/ENVIRONMENT.md) · 🇧🇩 [bn](../../bn/docs/reference/ENVIRONMENT.md) · 🇨🇿 [cs](../../cs/docs/reference/ENVIRONMENT.md) · 🇩🇰 [da](../../da/docs/reference/ENVIRONMENT.md) · 🇩🇪 [de](../../de/docs/reference/ENVIRONMENT.md) · 🇪🇸 [es](../../es/docs/reference/ENVIRONMENT.md) · 🇮🇷 [fa](../../fa/docs/reference/ENVIRONMENT.md) · 🇫🇮 [fi](../../fi/docs/reference/ENVIRONMENT.md) · 🇫🇷 [fr](../../fr/docs/reference/ENVIRONMENT.md) · 🇮🇳 [gu](../../gu/docs/reference/ENVIRONMENT.md) · 🇮🇱 [he](../../he/docs/reference/ENVIRONMENT.md) · 🇮🇳 [hi](../../hi/docs/reference/ENVIRONMENT.md) · 🇭🇺 [hu](../../hu/docs/reference/ENVIRONMENT.md) · 🇮🇩 [id](../../id/docs/reference/ENVIRONMENT.md) · 🇮🇹 [it](../../it/docs/reference/ENVIRONMENT.md) · 🇯🇵 [ja](../../ja/docs/reference/ENVIRONMENT.md) · 🇰🇷 [ko](../../ko/docs/reference/ENVIRONMENT.md) · 🇮🇳 [mr](../../mr/docs/reference/ENVIRONMENT.md) · 🇲🇾 [ms](../../ms/docs/reference/ENVIRONMENT.md) · 🇳🇱 [nl](../../nl/docs/reference/ENVIRONMENT.md) · 🇳🇴 [no](../../no/docs/reference/ENVIRONMENT.md) · 🇵🇭 [phi](../../phi/docs/reference/ENVIRONMENT.md) · 🇵🇱 [pl](../../pl/docs/reference/ENVIRONMENT.md) · 🇵🇹 [pt](../../pt/docs/reference/ENVIRONMENT.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/reference/ENVIRONMENT.md) · 🇷🇴 [ro](../../ro/docs/reference/ENVIRONMENT.md) · 🇷🇺 [ru](../../ru/docs/reference/ENVIRONMENT.md) · 🇸🇰 [sk](../../sk/docs/reference/ENVIRONMENT.md) · 🇸🇪 [sv](../../sv/docs/reference/ENVIRONMENT.md) · 🇰🇪 [sw](../../sw/docs/reference/ENVIRONMENT.md) · 🇮🇳 [ta](../../ta/docs/reference/ENVIRONMENT.md) · 🇮🇳 [te](../../te/docs/reference/ENVIRONMENT.md) · 🇹🇭 [th](../../th/docs/reference/ENVIRONMENT.md) · 🇹🇷 [tr](../../tr/docs/reference/ENVIRONMENT.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/reference/ENVIRONMENT.md) · 🇵🇰 [ur](../../ur/docs/reference/ENVIRONMENT.md) · 🇻🇳 [vi](../../vi/docs/reference/ENVIRONMENT.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/reference/ENVIRONMENT.md)
---
> Complete reference for every environment variable recognized by OmniRoute.
> For a quick-start template, see [`.env.example`](../.env.example).
> OmniRoute tarafından tanınan her ortam değişkeni için eksiksiz başvuru kılavuzu.
> Hızlı başlangıç şablonu için [`.env.example`](../../../../.env.example) dosyasına bakın.
> [!IMPORTANT]
> Burada belgelenen her değişken aynı zamanda `.env.example` içinde yer almalı ve `.env.example` içindeki her değişken burada görünmelidir. `npm run check:env-doc-sync` bunu commit sırasında ve CI üzerinde zorunlu kılar.
---
## Table of Contents
## İçindekiler
- [1. Required Secrets](#1-required-secrets)
- [2. Storage & Database](#2-storage--database)
- [3. Network & Ports](#3-network--ports)
- [4. Security & Authentication](#4-security--authentication)
- [5. Input Sanitization & PII Protection](#5-input-sanitization--pii-protection)
- [6. Tool & Routing Policies](#6-tool--routing-policies)
- [7. URLs & Cloud Sync](#7-urls--cloud-sync)
- [8. Outbound Proxy](#8-outbound-proxy)
- [9. CLI Tool Integration](#9-cli-tool-integration)
- [10. Internal Agent & MCP Integrations](#10-internal-agent--mcp-integrations)
- [11. OAuth Provider Credentials](#11-oauth-provider-credentials)
- [12. Provider User-Agent Overrides](#12-provider-user-agent-overrides)
- [13. CLI Fingerprint Compatibility](#13-cli-fingerprint-compatibility)
- [14. API Key Providers](#14-api-key-providers)
- [15. Timeout Settings](#15-timeout-settings)
- [16. Logging](#16-logging)
- [17. Memory Optimization](#17-memory-optimization)
- [18. Pricing Sync](#18-pricing-sync)
- [19. Model Sync (Dev)](#19-model-sync-dev)
- [20. Provider-Specific Settings](#20-provider-specific-settings)
- [21. Proxy Health](#21-proxy-health)
- [22. Debugging](#22-debugging)
- [23. GitHub Integration](#23-github-integration)
- [Deployment Scenarios](#deployment-scenarios)
- [Audit: Removed / Dead Variables](#audit-removed--dead-variables)
- [1. Zorunlu Sırlar](#1-zorunlu-sırlar)
- [2. Depolama ve Veritabanı](#2-depolama-ve-veritabanı)
- [3. Ağ ve Portlar](#3-ağ-ve-portlar)
- [4. Güvenlik ve Kimlik Doğrulama](#4-güvenlik-ve-kimlik-doğrulama)
- [5. Girdi Temizleme ve PII Koruması](#5-girdi-temizleme-ve-pii-koruması)
- [6. Araç ve Yönlendirme Politikaları](#6-araç-ve-yönlendirme-politikaları)
- [7. URL'ler ve Bulut Senkronizasyonu](#7-urller-ve-bulut-senkronizasyonu)
- [8. Giden Proxy (Outbound Proxy)](#8-giden-proxy)
- [9. CLI Araç Entegrasyonu](#9-cli-araç-entegrasyonu)
- [10. Dahili Ajan ve MCP Entegrasyonları](#10-dahili-ajan-ve-mcp-entegrasyonları)
- [11. OAuth Sağlayıcı Kimlik Bilgileri](#11-oauth-sağlayıcı-kimlik-bilgileri)
- [12. Sağlayıcı User-Agent Geçersiz Kılmaları](#12-sağlayıcı-user-agent-geçersiz-kılmaları)
- [13. CLI Parmak İzi Uyumluluğu](#13-cli-parmak-izi-uyumluluğu)
- [14. API Anahtarı Sağlayıcıları](#14-api-anahtarı-sağlayıcıları)
- [15. Zaman Aşımı Ayarları](#15-zaman-aşımı-ayarları)
- [16. Günlük Kaydı (Logging)](#16-günlük-kaydı)
- [17. Bellek Optimizasyonu](#17-bellek-optimizasyonu)
- [18. Fiyatlandırma Senkronizasyonu](#18-fiyatlandırma-senkronizasyonu)
- [19. Model Senkronizasyonu](#19-model-senkronizasyonu)
- [20. Sağlayıcıya Özel Ayarlar](#20-sağlayıcıya-özel-ayarlar)
- [21. Proxy Sağlığı](#21-proxy-sağlığı)
- [22. Hata Ayıklama (Debug)](#22-hata-ayıklama)
---
## 1. Required Secrets
## 1. Zorunlu Sırlar
These **must** be set before the first run. Without them, the application will either refuse to start or operate with insecure defaults.
Bunlar ilk çalıştırmadan önce **mutlaka** ayarlanmalıdır. Bunlar olmadan uygulama ya başlamayı reddeder ya da güvensiz varsayılanlarla çalışır.
| Variable | Required | Default | Source File | Description |
| ------------------ | -------- | -------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `JWT_SECRET` | **Yes** | _(none)_ | `src/lib/auth` | Signs/verifies all dashboard session cookies (JWT). Generate with `openssl rand -base64 48`. |
| `API_KEY_SECRET` | **Yes** | _(none)_ | `src/lib/db/apiKeys.ts` | AES encryption key for API key values at rest in SQLite. Generate with `openssl rand -hex 32`. |
| `INITIAL_PASSWORD` | **Yes** | `123456` | Bootstrap script | Sets the initial admin dashboard password. **Change before first use.** After login, change via Dashboard → Settings → Security. |
| Değişken | Zorunlu | Varsayılan | Kaynak Dosya | Açıklama |
| ---------------------------- | -------------------- | ----------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `JWT_SECRET` | **Evet** | _(yok)_ | `src/lib/auth` | Tüm pano oturum çerezlerini (JWT) imzalar ve doğrular. `openssl rand -base64 48` ile üretin. |
| `API_KEY_SECRET` | **Evet** | _(yok)_ | `src/lib/db/apiKeys.ts` | SQLite'ta saklanan API anahtarı değerleri için AES şifreleme anahtarı. `openssl rand -hex 32` ile üretin. |
| `INITIAL_PASSWORD` | **Evet** | `CHANGEME` | Bootstrap betiği | İlk yönetici pano şifresini belirler. **İlk kullanımdan önce değiştirin.** |
| `OMNIROUTE_WS_BRIDGE_SECRET` | **Evet** (üretimde) | _(ayarlanmamış)_ | `src/app/api/internal/codex-responses-ws/route.ts` | Dahili Codex Responses WebSocket köprüsü için paylaşılan sır. `openssl rand -base64 32` ile üretin. |
### Generation Commands
### Üretim Komutları
```bash
# Generate all three secrets at once:
# Dört sırrı tek seferde üretin:
echo "JWT_SECRET=$(openssl rand -base64 48)"
echo "API_KEY_SECRET=$(openssl rand -hex 32)"
echo "INITIAL_PASSWORD=$(openssl rand -base64 16)"
```
> [!CAUTION]
> Never commit `.env` files with real secrets to version control. The `.gitignore` already excludes `.env`, but verify before pushing.
---
## 2. Storage & Database
OmniRoute uses **SQLite** (via `better-sqlite3`) for all persistence. These variables control data location, encryption, and lifecycle.
| Variable | Default | Source File | Description |
| -------------------------------- | -------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `DATA_DIR` | `~/.omniroute/` | `src/lib/db/core.ts` | Root directory for SQLite DB, backups, and data files. Override for Docker volumes or custom paths. |
| `STORAGE_ENCRYPTION_KEY` | _(empty = disabled)_ | `src/lib/db/encryption.ts` | AES key for full SQLite database encryption at rest. Generate with `openssl rand -hex 32`. |
| `STORAGE_ENCRYPTION_KEY_VERSION` | `v1` | `scripts/bootstrap-env.mjs`, `electron/main.js` | Version label for the encryption key. Increment when performing key rotation to support decryption of old backups. |
| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | `src/lib/db/backup.ts` | When `true`, skips the automatic database backup that runs before migrations on every startup. |
| `OMNIROUTE_CRYPT_KEY` | _(unset)_ | `src/lib/db/encryption.ts` | **Legacy alias** for `STORAGE_ENCRYPTION_KEY`. Accepted as a fallback when the primary variable is absent. |
| `OMNIROUTE_API_KEY_BASE64` | _(unset)_ | `src/lib/db/encryption.ts` | **Legacy alias** (Base64-encoded form) accepted as a fallback. Decoded automatically before use. |
### Scenarios
| Scenario | Configuration |
| --------------------- | -------------------------------------------------------------------------------- |
| **Local development** | Leave all defaults. DB lives at `~/.omniroute/omniroute.db`. |
| **Docker** | `DATA_DIR=/data` + mount a volume at `/data`. |
| **Encrypted at rest** | Set `STORAGE_ENCRYPTION_KEY` + keep backups of the key! Losing it = losing data. |
| **CI/Testing** | `DATA_DIR=/tmp/omniroute-test` — ephemeral, no encryption needed. |
---
## 3. Network & Ports
| Variable | Default | Source File | Description |
| --------------------- | ------------ | -------------------------- | -------------------------------------------------------------------------------------- |
| `PORT` | `20128` | `src/lib/runtime/ports.ts` | Primary port for both Dashboard UI and API endpoints (single-port mode). |
| `API_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | When set, serves the `/v1/*` proxy API on this separate port. |
| `API_HOST` | `0.0.0.0` | `src/lib/runtime/ports.ts` | Bind address for the API port. |
| `DASHBOARD_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | When set, serves the Dashboard UI on this separate port. |
| `PROD_DASHBOARD_PORT` | `20130` | `docker-compose.prod.yml` | Host-side published port for the Dashboard in Docker production mode. |
| `PROD_API_PORT` | `20131` | `docker-compose.prod.yml` | Host-side published port for the API in Docker production mode. |
| `OMNIROUTE_PORT` | _(unset)_ | `src/lib/runtime/ports.ts` | Takes precedence over `PORT` when running inside Electron or other wrappers. |
| `NODE_ENV` | `production` | Next.js core | Controls logging verbosity, caching, error detail exposure, and Next.js optimizations. |
### Port Modes
```
┌─────────────────────────── Single Port (default) ──────────────────────────┐
│ PORT=20128 │
│ → Dashboard: http://localhost:20128 │
│ → API: http://localhost:20128/v1/chat/completions │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────── Split Ports ─────────────────────────────────────┐
│ DASHBOARD_PORT=20128 │
│ API_PORT=20129 │
│ API_HOST=0.0.0.0 │
│ → Dashboard: http://localhost:20128 │
│ → API: http://0.0.0.0:20129/v1/chat/completions │
│ Use case: Expose API to LAN while restricting Dashboard to localhost. │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────── Docker Production ──────────────────────────────┐
│ PROD_DASHBOARD_PORT=443 PROD_API_PORT=8443 │
│ → Maps container ports to host ports in docker-compose.prod.yml. │
└─────────────────────────────────────────────────────────────────────────────┘
echo "OMNIROUTE_WS_BRIDGE_SECRET=$(openssl rand -base64 32)"
```
---
## 4. Security & Authentication
## 2. Depolama ve Veritabanı
| Variable | Default | Source File | Description |
| ----------------------------- | --------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `MACHINE_ID_SALT` | `endpoint-proxy-salt` | `src/lib/auth` | Salt combined with hardware identifiers for machine fingerprinting. Change per-deployment for isolation. |
| `AUTH_COOKIE_SECURE` | `false` | `src/lib/auth` | Sets the `Secure` flag on session cookies. **Must be `true`** when running behind HTTPS. |
| `REQUIRE_API_KEY` | `false` | API middleware | When `true`, all `/v1/*` proxy requests must include a valid API key. |
| `ALLOW_API_KEY_REVEAL` | `false` | Dashboard providers page | Allows revealing full API key values in the Dashboard UI. Security risk on shared instances. |
| `NO_LOG_API_KEY_IDS` | _(empty)_ | `src/lib/compliance/index.ts` | Comma-separated API key IDs that bypass request logging (GDPR compliance). |
| `MAX_BODY_SIZE_BYTES` | `10485760` (10 MB) | `src/shared/middleware/bodySizeGuard.ts` | Maximum allowed request body size. Rejects payloads exceeding this limit. |
| `CORS_ORIGIN` | `*` | Next.js middleware | CORS `Access-Control-Allow-Origin` value. Restrict for production. |
| `OUTBOUND_SSRF_GUARD_ENABLED` | `true` | `src/shared/network/outboundUrlGuard.ts` | Block provider calls targeting private/loopback/link-local IP ranges. Disable only in isolated test envs. |
### Hardening Checklist
```bash
# Production security minimum:
AUTH_COOKIE_SECURE=true # Requires HTTPS
REQUIRE_API_KEY=true # Authenticate all proxy calls
ALLOW_API_KEY_REVEAL=false # Never expose keys in UI
CORS_ORIGIN=https://your.domain.com
MAX_BODY_SIZE_BYTES=5242880 # 5 MB limit
```
| Değişken | Varsayılan | ıklama |
| -------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------ |
| `DATA_DIR` | `~/.omniroute/` | SQLite veritabanı, yedeklemeler ve veri dosyaları için kök dizin. Docker hacimleri için geçersiz kılın. |
| `STORAGE_ENCRYPTION_KEY` | _(boş = devre dışı)_ | SQLite veritabanının diskte AES ile şifrelenmesi için anahtar. `openssl rand -hex 32` ile üretin. |
| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | `true` olduğunda otomatik başlatma ve yazma öncesi yedeklemeleri atlar. |
| `OMNIROUTE_WAL_TRUNCATE_INTERVAL_MS` | `21600000` (6h) | Periyodik `wal_checkpoint(TRUNCATE)` aralığı (ms). |
---
## 5. Input Sanitization & PII Protection
OmniRoute provides a two-layer defense: request-side injection scanning and response-side PII stripping.
### Request-Side: Prompt Injection Guard
| Variable | Default | Source File | Description |
| ------------------------- | --------- | ---------------------------------------- | ------------------------------------------------------------------------------------------- |
| `INPUT_SANITIZER_ENABLED` | `true` | `src/middleware/promptInjectionGuard.ts` | Enable scanning of incoming messages for prompt injection patterns. |
| `INPUT_SANITIZER_MODE` | `warn` | `src/middleware/promptInjectionGuard.ts` | `warn` = log only, `block` = reject request with 400, `redact` = strip suspicious patterns. |
| `INJECTION_GUARD_MODE` | _(unset)_ | `src/middleware/promptInjectionGuard.ts` | Legacy alias for `INPUT_SANITIZER_MODE` — same behavior. |
| `PII_REDACTION_ENABLED` | `false` | `src/middleware/promptInjectionGuard.ts` | Detect PII (emails, phones, SSNs) in incoming requests. |
### Response-Side: PII Sanitizer
| Variable | Default | Source File | Description |
| -------------------------------- | -------- | ------------------------- | ----------------------------------------------------------------------- |
| `PII_RESPONSE_SANITIZATION` | `false` | `src/lib/piiSanitizer.ts` | Scan LLM responses for leaked PII before returning to client. |
| `PII_RESPONSE_SANITIZATION_MODE` | `redact` | `src/lib/piiSanitizer.ts` | `redact` = mask PII, `warn` = log only, `block` = drop entire response. |
### Scenarios
| Scenario | Configuration |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Enterprise compliance** | `INPUT_SANITIZER_ENABLED=true`, `INPUT_SANITIZER_MODE=block`, `PII_REDACTION_ENABLED=true`, `PII_RESPONSE_SANITIZATION=true` |
| **Monitoring only** | `INPUT_SANITIZER_ENABLED=true`, `INPUT_SANITIZER_MODE=warn` — logs but never blocks |
| **Personal use** | Leave all disabled — zero overhead |
---
## 6. Tool & Routing Policies
| Variable | Default | Source File | Description |
| ------------------ | ---------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `TOOL_POLICY_MODE` | `disabled` | `src/lib/toolPolicy.ts` | Controls LLM tool/function-calling access. `allowlist` = only listed tools, `denylist` = all except listed, `disabled` = no restrictions. |
---
## 7. URLs & Cloud Sync
| Variable | Default | Source File | Description |
| ----------------------- | ------------------------ | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `BASE_URL` | `http://localhost:20128` | `src/lib/cloudSync.ts` | Server-side URL for internal sync jobs to call `/api/sync/cloud`. |
| `CLOUD_URL` | _(empty)_ | `src/lib/cloudSync.ts` | Cloud relay endpoint URL (premium feature). |
| `CLOUD_SYNC_TIMEOUT_MS` | `12000` | `src/lib/cloudSync.ts` | HTTP timeout for cloud sync requests. |
| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | OAuth, Dashboard, sync | Public-facing URL for OAuth redirect_uri, Dashboard links. **Must match your public URL behind reverse proxy.** |
| `NEXT_PUBLIC_CLOUD_URL` | _(empty)_ | Client-side | Client-side mirror of `CLOUD_URL`. |
| `NEXT_PUBLIC_APP_URL` | _(unset)_ | `src/shared/services/cloudSyncScheduler.ts` | Legacy fallback for `NEXT_PUBLIC_BASE_URL`. |
> [!IMPORTANT]
> When deploying behind a reverse proxy (nginx, Caddy), `NEXT_PUBLIC_BASE_URL` **must** be set to your public URL (e.g., `https://omniroute.example.com`). Without this, OAuth callbacks will fail because the redirect_uri won't match.
---
## 8. Outbound Proxy
Route upstream LLM provider calls through an HTTP or SOCKS5 proxy for egress control, geo-routing, or IP masking.
| Variable | Default | Source File | Description |
| --------------------------------- | --------- | -------------------- | ----------------------------------------------------------------------------------- |
| `ENABLE_SOCKS5_PROXY` | `true` | `open-sse/executors` | Enable SOCKS5 proxy agent for upstream calls. |
| `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` | `true` | Client-side | Client-side awareness of SOCKS5 availability. |
| `HTTP_PROXY` | _(unset)_ | Node.js standard | HTTP proxy for upstream calls. |
| `HTTPS_PROXY` | _(unset)_ | Node.js standard | HTTPS proxy for upstream calls. |
| `ALL_PROXY` | _(unset)_ | Node.js standard | Universal proxy (supports `socks5://`). |
| `NO_PROXY` | _(unset)_ | Node.js standard | Comma-separated hostnames/IPs to bypass the proxy. |
| `ENABLE_TLS_FINGERPRINT` | `false` | `open-sse/executors` | Spoof TLS fingerprint using wreq-js (mimics Chrome 124). Counters JA3/JA4 blocking. |
### Scenarios
| Scenario | Configuration |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| **SOCKS5 through SSH tunnel** | `ALL_PROXY=socks5://127.0.0.1:7890`, `ENABLE_SOCKS5_PROXY=true` |
| **Corporate HTTP proxy** | `HTTP_PROXY=http://proxy.corp.com:3128`, `HTTPS_PROXY=http://proxy.corp.com:3128`, `NO_PROXY=localhost,internal.corp.com` |
| **Anti-fingerprint** | `ENABLE_TLS_FINGERPRINT=true` — requires `wreq-js` (included) |
---
## 9. CLI Tool Integration
Controls how OmniRoute discovers and launches CLI sidecars (Claude Code, Codex, etc.).
| Variable | Default | Source File | Description |
| ------------------------- | ---------- | ----------------------------------- | -------------------------------------------------------------------------- |
| `CLI_MODE` | `auto` | `src/shared/services/cliRuntime.ts` | `auto` = search system PATH; `manual` = use explicit paths only. |
| `CLI_EXTRA_PATHS` | _(unset)_ | `src/shared/services/cliRuntime.ts` | Additional PATH entries for CLI binary discovery (colon-separated). |
| `CLI_CONFIG_HOME` | _(unset)_ | `src/shared/services/cliRuntime.ts` | Override home directory for reading CLI configs (`~/.claude`, `~/.codex`). |
| `CLI_ALLOW_CONFIG_WRITES` | `false` | `src/shared/services/cliRuntime.ts` | Allow OmniRoute to write CLI config files (token refresh, session data). |
| `CLI_CLAUDE_BIN` | `claude` | `src/shared/services/cliRuntime.ts` | Custom path to Claude CLI binary. |
| `CLI_CODEX_BIN` | `codex` | `src/shared/services/cliRuntime.ts` | Custom path to Codex CLI binary. |
| `CLI_DROID_BIN` | `droid` | `src/shared/services/cliRuntime.ts` | Custom path to Droid CLI binary. |
| `CLI_OPENCLAW_BIN` | `openclaw` | `src/shared/services/cliRuntime.ts` | Custom path to OpenClaw CLI binary. |
| `CLI_CURSOR_BIN` | `agent` | `src/shared/services/cliRuntime.ts` | Custom path to Cursor agent binary. |
| `CLI_CLINE_BIN` | `cline` | `src/shared/services/cliRuntime.ts` | Custom path to Cline CLI binary. |
| `CLI_CONTINUE_BIN` | `cn` | `src/shared/services/cliRuntime.ts` | Custom path to Continue CLI binary. |
| `CLI_QODER_BIN` | `qoder` | `src/shared/services/cliRuntime.ts` | Custom path to Qoder CLI binary. |
### Docker Example
```bash
# Mount host binaries into the container and tell OmniRoute where they are:
CLI_EXTRA_PATHS=/host-cli/bin
CLI_CONFIG_HOME=/root
CLI_ALLOW_CONFIG_WRITES=true
CLI_CLAUDE_BIN=/host-cli/bin/claude
```
---
## 10. Internal Agent & MCP Integrations
| Variable | Default | Source File | Description |
| --------------------------------------- | ----------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_BASE_URL` | auto-detect | `open-sse/mcp-server/server.ts` | Explicit URL for MCP/A2A tools to reach OmniRoute. Overrides localhost auto-detection. |
| `OMNIROUTE_API_KEY` | _(unset)_ | MCP/A2A modules | API key for internal MCP tool and A2A skill calls. |
| `OMNIROUTE_API_KEY_ID` | _(unset)_ | `open-sse/mcp-server/audit.ts` | Key ID for MCP audit log attribution. |
| `ROUTER_API_KEY` | _(unset)_ | Legacy | Legacy alias for `OMNIROUTE_API_KEY`. |
| `OMNIROUTE_MCP_ENFORCE_SCOPES` | `false` | `open-sse/mcp-server/server.ts` | Enforce scope-based access control on MCP tool calls. |
| `OMNIROUTE_MCP_SCOPES` | _(all)_ | `open-sse/mcp-server/server.ts` | Comma-separated scopes: `admin`, `combos`, `health`, `models`, `routing`, `budget`, `metrics`, `pricing`, `memory`, `skills`. |
| `MODEL_SYNC_INTERVAL_HOURS` | `24` | `src/shared/services/modelSyncScheduler.ts` | Model catalog sync interval in hours. |
| `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | `src/server-init.ts` | Provider rate-limit and quota polling interval. |
| `OMNIROUTE_DISABLE_BACKGROUND_SERVICES` | `false` | `src/instrumentation-node.ts` | Disable all background services (sync, pricing, model refresh). Useful for CI/test. |
| `OMNIROUTE_BOOTSTRAPPED` | `false` | `src/app/(dashboard)/dashboard/page.tsx` | Set `true` by bootstrap script after initial setup. Controls setup wizard visibility. |
| `OMNIROUTE_ALLOW_BODY_PROJECT_OVERRIDE` | `0` | `open-sse/executors/antigravity.ts` | Escape hatch: allow request body to override the Antigravity project field. |
### OAuth CLI Bridge (Internal)
| Variable | Default | Source File | Description |
| ------------------- | ----------- | ------------------------------- | ----------------------------------------- |
| `OMNIROUTE_SERVER` | auto-detect | `src/lib/oauth/config/index.ts` | Server URL for CLI↔OmniRoute auth bridge. |
| `OMNIROUTE_TOKEN` | _(unset)_ | `src/lib/oauth/config/index.ts` | Auth token for CLI bridge. |
| `OMNIROUTE_USER_ID` | `cli` | `src/lib/oauth/config/index.ts` | User ID for CLI bridge sessions. |
| `SERVER_URL` | _(unset)_ | `src/lib/oauth/config/index.ts` | Legacy alias for `OMNIROUTE_SERVER`. |
| `CLI_TOKEN` | _(unset)_ | `src/lib/oauth/config/index.ts` | Legacy alias for `OMNIROUTE_TOKEN`. |
| `CLI_USER_ID` | _(unset)_ | `src/lib/oauth/config/index.ts` | Legacy alias for `OMNIROUTE_USER_ID`. |
---
## 11. OAuth Provider Credentials
Built-in credentials for **localhost development**. For remote deployments, register your own at each provider's developer console.
| Variable | Provider | Notes |
| --------------------------------- | ----------------------- | --------------------------------------------------------------------------------- |
| `CLAUDE_OAUTH_CLIENT_ID` | Claude Code (Anthropic) | Public client — no secret needed. |
| `CLAUDE_CODE_REDIRECT_URI` | Claude Code | Override redirect URI. Default: `https://platform.claude.com/oauth/code/callback` |
| `CODEX_OAUTH_CLIENT_ID` | Codex / OpenAI | Public client. |
| `GEMINI_OAUTH_CLIENT_ID` | Gemini (Google) | Requires matching `_SECRET`. |
| `GEMINI_OAUTH_CLIENT_SECRET` | Gemini (Google) | — |
| `QWEN_OAUTH_CLIENT_ID` | Qwen (Alibaba) | Public client. |
| `KIMI_CODING_OAUTH_CLIENT_ID` | Kimi Coding (Moonshot) | Public client. |
| `ANTIGRAVITY_OAUTH_CLIENT_ID` | Antigravity (Google) | Requires matching `_SECRET`. |
| `ANTIGRAVITY_OAUTH_CLIENT_SECRET` | Antigravity (Google) | — |
| `GITHUB_OAUTH_CLIENT_ID` | GitHub Copilot | Public client. |
| `QODER_OAUTH_CLIENT_SECRET` | Qoder | — |
| `QODER_OAUTH_AUTHORIZE_URL` | Qoder | Set to enable Qoder OAuth. |
| `QODER_OAUTH_TOKEN_URL` | Qoder | — |
| `QODER_OAUTH_USERINFO_URL` | Qoder | — |
| `QODER_OAUTH_CLIENT_ID` | Qoder | — |
| `QODER_PERSONAL_ACCESS_TOKEN` | Qoder | Direct API key fallback (bypasses OAuth). |
| `QODER_CLI_WORKSPACE` | Qoder | Workspace ID for Qoder CLI. |
| `OMNIROUTE_QODER_WORKSPACE` | Qoder | Alias for `QODER_CLI_WORKSPACE`. |
> [!WARNING]
>
> 1. Go to [Google Cloud Console → Credentials](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
> 4. Replace the credential values in `.env`.
---
## 12. Provider User-Agent Overrides
Override the `User-Agent` header sent to each upstream provider. This is dynamically resolved at runtime by the executor base class:
```
process.env[`${PROVIDER_ID}_USER_AGENT`]
```
> **Source:** `open-sse/executors/base.ts` → `buildHeaders()`
| Variable | Default Value | When to Update |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
| `CLAUDE_USER_AGENT` | `claude-cli/2.1.219 (external, cli)` | When Anthropic releases a new CLI version |
| `CODEX_USER_AGENT` | `codex-cli/0.132.0 (Windows 10.0.26200; x64)` | When OpenAI updates the Codex CLI |
| `CODEX_CLIENT_VERSION` | `0.131.0` | Override Codex client version independently of full UA string |
| `GITHUB_USER_AGENT` | `GitHubCopilotChat/0.45.1` | When GitHub Copilot Chat updates |
| `ANTIGRAVITY_USER_AGENT` | `antigravity/2.0.1 darwin/arm64` | When Antigravity IDE updates |
| `KIRO_USER_AGENT` | `AWS-SDK-JS/3.0.0 kiro-ide/1.0.0` | When Kiro IDE updates |
| `QODER_USER_AGENT` | `Qoder-Cli` | When Qoder CLI updates |
| `QWEN_USER_AGENT` | `QwenCode/0.15.11 (linux; x64)` | When Qwen Code updates |
| `CURSOR_USER_AGENT` | `connect-es/1.6.1` | When Cursor updates |
> [!TIP]
> You can add User-Agent overrides for **any** provider using the pattern `{PROVIDER_ID}_USER_AGENT`. The executor dynamically constructs the env var name.
---
## 13. CLI Fingerprint Compatibility
When enabled, OmniRoute reorders HTTP headers and JSON body fields to match the exact signature of official CLI tools. This reduces the risk of account flagging while preserving your proxy IP.
**Source:** `open-sse/config/cliFingerprints.ts`, `open-sse/executors/base.ts`
### Per-Provider
| Variable | Effect |
| -------------------------- | --------------------------------------- |
| `CLI_COMPAT_CODEX=1` | Mimics Codex CLI request signature |
| `CLI_COMPAT_CLAUDE=1` | Mimics Claude Code request signature |
| `CLI_COMPAT_GITHUB=1` | Mimics GitHub Copilot request signature |
| `CLI_COMPAT_ANTIGRAVITY=1` | Mimics Antigravity request signature |
| `CLI_COMPAT_KIRO=1` | Mimics Kiro IDE request signature |
| `CLI_COMPAT_CURSOR=1` | Mimics Cursor request signature |
| `CLI_COMPAT_KIMI_CODING=1` | Mimics Kimi Coding request signature |
| `CLI_COMPAT_KILOCODE=1` | Mimics Kilo Code request signature |
| `CLI_COMPAT_CLINE=1` | Mimics Cline request signature |
| `CLI_COMPAT_QWEN=1` | Mimics Qwen Code request signature |
### Global
| Variable | Effect |
| ------------------ | --------------------------------------------------------------- |
| `CLI_COMPAT_ALL=1` | Enable fingerprint compatibility for **all** providers at once. |
> [!NOTE]
> This feature works alongside the User-Agent overrides (§12). The fingerprint system handles header ordering and body field ordering, while User-Agent overrides handle the specific UA string. Both can be enabled independently.
---
## 14. API Key Providers
API keys for providers that use direct authentication. **Preferred setup:** Dashboard → Providers → Add API Key.
Setting via environment variables is an alternative for Docker or headless deployments.
Recognized pattern: `{PROVIDER_ID}_API_KEY`
| Variable | Provider |
| -------------------- | ------------------- |
| `DEEPSEEK_API_KEY` | DeepSeek |
| `GROQ_API_KEY` | Groq |
| `XAI_API_KEY` | xAI (Grok) |
| `MISTRAL_API_KEY` | Mistral AI |
| `PERPLEXITY_API_KEY` | Perplexity |
| `TOGETHER_API_KEY` | Together AI |
| `FIREWORKS_API_KEY` | Fireworks AI |
| `CEREBRAS_API_KEY` | Cerebras |
| `COHERE_API_KEY` | Cohere |
| `NVIDIA_API_KEY` | NVIDIA NIM |
| `NEBIUS_API_KEY` | Nebius (embeddings) |
> [!TIP]
> Keys set via the Dashboard are stored encrypted in SQLite and take precedence over environment variables.
---
## 15. Timeout Settings
All values are in **milliseconds**. Centralized resolution in `src/shared/utils/runtimeTimeouts.ts`.
### Timeout Hierarchy
```
REQUEST_TIMEOUT_MS (global override)
├─→ FETCH_TIMEOUT_MS (upstream provider calls, default: 600000)
│ ├─→ FETCH_HEADERS_TIMEOUT_MS (inherits from FETCH_TIMEOUT_MS)
│ ├─→ FETCH_BODY_TIMEOUT_MS (inherits from FETCH_TIMEOUT_MS)
│ ├─→ TLS_CLIENT_TIMEOUT_MS (inherits from FETCH_TIMEOUT_MS)
│ ├── FETCH_CONNECT_TIMEOUT_MS (independent, default: 30000)
│ └── FETCH_KEEPALIVE_TIMEOUT_MS (independent, default: 4000)
├─→ STREAM_IDLE_TIMEOUT_MS (inherits from REQUEST_TIMEOUT_MS, default: 600000)
└─→ API_BRIDGE_PROXY_TIMEOUT_MS (inherits from REQUEST_TIMEOUT_MS, default: 600000)
├─→ API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS (derived, default: 600000)
├── API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS (default: 60000)
├── API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS (default: 5000)
└── API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS (default: 0 = disabled)
```
| Variable | Default | Description |
| ---------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------- |
| `REQUEST_TIMEOUT_MS` | _(unset)_ | Global shortcut — overrides both `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` defaults. |
| `FETCH_TIMEOUT_MS` | `600000` | Total HTTP request timeout for upstream provider calls. |
| `STREAM_IDLE_TIMEOUT_MS` | `600000` | Max silence between SSE chunks before aborting. Extended-thinking models rarely pause >90s. |
| `FETCH_HEADERS_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | Time to receive response headers. |
| `FETCH_BODY_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | Time to receive the full response body. |
| `FETCH_CONNECT_TIMEOUT_MS` | `30000` | TCP connection establishment timeout. |
| `FETCH_KEEPALIVE_TIMEOUT_MS` | `4000` | Keep-alive socket idle timeout. |
| `TLS_CLIENT_TIMEOUT_MS` | = `FETCH_TIMEOUT_MS` | TLS fingerprint proxy (wreq-js) timeout. |
| `API_BRIDGE_PROXY_TIMEOUT_MS` | `600000` | Proxy hop timeout for `/v1` bridge requests. |
| `API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS` | `600000` | Overall server request timeout for the bridge. |
| `API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS` | `60000` | Time to send response headers via the bridge. |
| `API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS` | `5000` | Bridge keep-alive idle timeout. |
| `API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS` | `0` | Raw socket timeout (0 = disabled). |
| `SHUTDOWN_TIMEOUT_MS` | `30000` | Grace period on SIGTERM/SIGINT before force-exit. |
### Scenarios
| Scenario | Configuration |
| -------------------------------- | ------------------------------------------------------ |
| **Long-running code generation** | `REQUEST_TIMEOUT_MS=900000` (15 min) |
| **Fast-fail for production API** | `API_BRIDGE_PROXY_TIMEOUT_MS=10000` |
| **Extended thinking models** | `STREAM_IDLE_TIMEOUT_MS=300000` (5 min between chunks) |
---
## 16. Logging
The logging system writes to both stdout and rotated log files. All configuration is read by `src/lib/logEnv.ts`.
| Variable | Default | Description |
| --------------------------- | -------------------------- | ---------------------------------------------------------------------------- |
| `APP_LOG_LEVEL` | `info` | Minimum log level: `debug`, `info`, `warn`, `error`. |
| `APP_LOG_FORMAT` | `text` | Output format: `text` (human-readable) or `json` (structured). |
| `APP_LOG_TO_FILE` | `true` | Write logs to file alongside stdout. |
| `APP_LOG_FILE_PATH` | `logs/application/app.log` | Log file path (relative to project root or `DATA_DIR`). |
| `APP_LOG_MAX_FILE_SIZE` | `50M` | Max file size before rotation. Accepts: `50M`, `1G`, `512K`, or plain bytes. |
| `APP_LOG_RETENTION_DAYS` | `7` | Days to keep rotated application log files. |
| `APP_LOG_MAX_FILES` | `20` | Maximum rotated log file backups. |
| `CALL_LOG_RETENTION_DAYS` | `7` | Days to keep request/call log entries in the database. |
| `CALL_LOG_MAX_ENTRIES` | `10000` | Max call log entries in the in-memory buffer. |
| `CALL_LOGS_TABLE_MAX_ROWS` | `100000` | Max rows in the `call_logs` SQLite table before pruning. |
| `PROXY_LOGS_TABLE_MAX_ROWS` | `100000` | Max rows in the `proxy_logs` SQLite table before pruning. |
---
## 17. Memory Optimization
| Variable | Default | Description |
| -------------------------- | ------------------ | ---------------------------------------------------------------------------------------------------- |
| `OMNIROUTE_MEMORY_MB` | `512` | Runtime V8 heap limit. Docker standalone and `omniroute serve` use it to set `--max-old-space-size`. |
| `PROMPT_CACHE_MAX_SIZE` | `50` | Max cached system prompt entries. |
| `PROMPT_CACHE_MAX_BYTES` | `2097152` (2 MB) | Max total prompt cache size. |
| `PROMPT_CACHE_TTL_MS` | `300000` (5 min) | Prompt cache entry TTL. |
| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max cached temperature=0 responses. |
| `SEMANTIC_CACHE_MAX_BYTES` | `4194304` (4 MB) | Max total semantic cache size. |
| `SEMANTIC_CACHE_TTL_MS` | `1800000` (30 min) | Semantic cache entry TTL. |
| `STREAM_HISTORY_MAX` | `50` | Max recent stream events in the Dashboard live view buffer. |
| `CONTEXT_LENGTH_DEFAULT` | `128000` | Global fallback max context length for models without explicit config. |
| `USAGE_TOKEN_BUFFER` | `100` | Extra token headroom reserved when tracking usage quotas. |
### Low-RAM Docker Example
```bash
OMNIROUTE_MEMORY_MB=128
PROMPT_CACHE_MAX_SIZE=20
PROMPT_CACHE_MAX_BYTES=524288 # 512 KB
SEMANTIC_CACHE_MAX_SIZE=25
SEMANTIC_CACHE_MAX_BYTES=1048576 # 1 MB
STREAM_HISTORY_MAX=10
```
---
## 18. Pricing Sync
Automatic model pricing data synchronization from external sources.
| Variable | Default | Source File | Description |
| ----------------------- | ------------- | ------------------------ | ----------------------------- |
| `PRICING_SYNC_ENABLED` | `false` | `src/lib/pricingSync.ts` | Opt-in periodic pricing sync. |
| `PRICING_SYNC_INTERVAL` | `86400` (24h) | `src/lib/pricingSync.ts` | Sync interval in seconds. |
| `PRICING_SYNC_SOURCES` | `litellm` | `src/lib/pricingSync.ts` | Comma-separated data sources. |
---
## 19. Model Sync (Dev)
| Variable | Default | Source File | Description |
| -------------------------- | ------------- | -------------------------- | -------------------------------------------------------- |
| `MODELS_DEV_SYNC_INTERVAL` | `86400` (24h) | `src/lib/modelsDevSync.ts` | Development-time model catalog sync interval in seconds. |
---
## 20. Provider-Specific Settings
| Variable | Default | Source File | Description |
| ----------------------------------------- | ------------------ | ------------------------------------------ | ------------------------------------------------------------------------------------- |
| `OPENROUTER_CATALOG_TTL_MS` | `86400000` (24h) | `src/lib/catalog/openrouterCatalog.ts` | OpenRouter model catalog cache TTL. |
| `NANOBANANA_POLL_TIMEOUT_MS` | `120000` | `open-sse/handlers/imageGeneration.ts` | Max wait for NanoBanana image generation jobs. |
| `NANOBANANA_POLL_INTERVAL_MS` | `2500` | `open-sse/handlers/imageGeneration.ts` | NanoBanana job polling frequency. |
| `CLOUDFLARE_ACCOUNT_ID` | _(unset)_ | `open-sse/executors/cloudflare-ai.ts` | Account ID for Cloudflare Workers AI. |
| `CLOUDFLARED_BIN` | auto-detect | `src/lib/cloudflaredTunnel.ts` | Custom path to `cloudflared` binary. |
| `SEARCH_CACHE_TTL_MS` | `300000` (5 min) | `open-sse/services/searchCache.ts` | TTL for search API (Perplexity, Brave, etc.) response caching. |
| `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` | `false` | `src/app/api/providers/route.ts` | Allow multiple simultaneous connections per OpenAI-compatible provider. |
| `ENABLE_CC_COMPATIBLE_PROVIDER` | `false` | `src/shared/utils/featureFlags.ts` | Enable experimental Claude Code compatible provider endpoint. |
| `CLIPROXYAPI_HOST` | `127.0.0.1` | `open-sse/executors/cliproxyapi.ts` | CLIProxyAPI bridge host (legacy integration). |
| `CLIPROXYAPI_PORT` | `5544` | `open-sse/executors/cliproxyapi.ts` | CLIProxyAPI bridge port. |
| `CLIPROXYAPI_CONFIG_DIR` | `~/.cli-proxy-api` | `src/lib/versionManager/processManager.ts` | CLIProxyAPI config directory. |
| `LOCAL_HOSTNAMES` | _(empty)_ | `open-sse/config/providerRegistry.ts` | Comma-separated additional hostnames treated as "local" (Docker service names, etc.). |
---
## 21. Proxy Health
| Variable | Default | Source File | Description |
| ---------------------------- | ---------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `PROXY_FAST_FAIL_TIMEOUT_MS` | `2000` | `src/lib/proxyHealth.ts` | Fast-fail health check timeout. |
| `PROXY_HEALTH_CACHE_TTL_MS` | `30000` | `src/lib/proxyHealth.ts` | Health check result cache TTL. |
| `RATE_LIMIT_MAX_WAIT_MS` | `120000` (2 min) | `open-sse/services/rateLimitManager.ts` | Max time to wait on a 429 before failing the request. |
| `REQUEST_RETRY` | `2` | `src/sse/services/cooldownAwareRetry.ts` | Number of automatic retries on model-scoped cooldown responses before returning error to client. |
| `MAX_RETRY_INTERVAL_SEC` | `30` | `src/sse/services/cooldownAwareRetry.ts` | Max backoff interval (seconds) between cooldown retries. Capped by this value regardless of upstream `Retry-After`. |
---
## 22. Debugging
> [!CAUTION]
> These variables produce **verbose output** and may leak sensitive data. **Never enable in production.**
| Variable | Default | Source File | Description |
| -------------------------------- | --------- | ----------------------------------------- | -------------------------------------------------------------- |
| `CURSOR_PROTOBUF_DEBUG` | _(unset)_ | `open-sse/utils/cursorProtobuf.ts` | Set `1` to dump Cursor protobuf decode/encode details. |
| `CURSOR_STREAM_DEBUG` | _(unset)_ | `open-sse/executors/cursor.ts` | Set `1` to dump raw Cursor SSE stream data. |
| `DEBUG_RESPONSES_SSE_TO_JSON` | _(unset)_ | `open-sse/handlers/responseTranslator.ts` | Set `true` to log Responses API SSE→JSON translation details. |
| `NEXT_PUBLIC_OMNIROUTE_E2E_MODE` | _(unset)_ | E2E test harness | Set `true` to enable E2E test mode (relaxed auth, test hooks). |
---
## 23. GitHub Integration
Allow users to report issues directly from the Dashboard.
| Variable | Default | Source File | Description |
| --------------------- | --------- | --------------------------------------- | ------------------------------------------------------- |
| `GITHUB_ISSUES_REPO` | _(unset)_ | `src/app/api/v1/issues/report/route.ts` | Repository in `owner/repo` format. |
| `GITHUB_ISSUES_TOKEN` | _(unset)_ | `src/app/api/v1/issues/report/route.ts` | GitHub Personal Access Token with `issues:write` scope. |
---
## Deployment Scenarios
### Minimal Local Development
```bash
JWT_SECRET=$(openssl rand -base64 48)
API_KEY_SECRET=$(openssl rand -hex 32)
INITIAL_PASSWORD=dev123
PORT=20128
NODE_ENV=development
```
### Docker Production
```bash
JWT_SECRET=<generated>
API_KEY_SECRET=<generated>
INITIAL_PASSWORD=<generated>
STORAGE_ENCRYPTION_KEY=<generated>
DATA_DIR=/data
PORT=20128
API_PORT=20129
NODE_ENV=production
AUTH_COOKIE_SECURE=true
REQUIRE_API_KEY=true
NEXT_PUBLIC_BASE_URL=https://omniroute.example.com
BASE_URL=http://localhost:20128
OMNIROUTE_MEMORY_MB=512
CORS_ORIGIN=https://your-frontend.example.com
```
### Air-Gapped / CI
```bash
JWT_SECRET=test-jwt-secret-for-ci
API_KEY_SECRET=test-api-key-secret-for-ci
INITIAL_PASSWORD=testpass
NODE_ENV=production
OMNIROUTE_DISABLE_BACKGROUND_SERVICES=true
APP_LOG_TO_FILE=false
```
### VPS with Reverse Proxy (nginx + Cloudflare)
```bash
JWT_SECRET=<generated>
API_KEY_SECRET=<generated>
STORAGE_ENCRYPTION_KEY=<generated>
PORT=20128
AUTH_COOKIE_SECURE=true
REQUIRE_API_KEY=true
NEXT_PUBLIC_BASE_URL=https://omniroute.example.com
BASE_URL=http://127.0.0.1:20128
CORS_ORIGIN=https://omniroute.example.com
ENABLE_TLS_FINGERPRINT=true
CLI_COMPAT_ALL=1
```
---
## Audit: Removed / Dead Variables
The following variables appeared in previous versions of `.env.example` but have **no runtime references** in the current codebase. They have been removed:
| Variable | Reason |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `STORAGE_DRIVER=sqlite` | Never read by any source file. SQLite is the only supported driver — no selection needed. |
| `INSTANCE_NAME=omniroute` | Present in old docs/env templates but unused at runtime. May return in a future multi-instance feature. |
| `SQLITE_MAX_SIZE_MB=2048` | Not referenced in source code. Database size is not artificially limited. |
| `SQLITE_CLEAN_LEGACY_FILES=true` | Not referenced in source code. Legacy cleanup was likely removed. |
| `CLI_ROO_BIN` | Not registered in `src/shared/services/cliRuntime.ts`. |
| `CLI_KIMI_CODING_BIN` | Not registered in `src/shared/services/cliRuntime.ts` (Kimi Coding uses OAuth, not a CLI binary). |
| `IFLOW_OAUTH_CLIENT_ID` / `IFLOW_OAUTH_CLIENT_SECRET` | Not referenced anywhere in source code. |
### Default Value Corrections
| Variable | Old `.env.example` Value | Actual Code Default | Fixed |
| ------------------------- | ------------------------ | ------------------- | ------------------------------------------------------ |
| `APP_LOG_RETENTION_DAYS` | `90` | `7` | ✅ Removed misleading value; documented `7` as default |
| `CALL_LOG_RETENTION_DAYS` | `90` | `7` | ✅ Removed misleading value; documented `7` as default |
## 3. Ağ ve Portlar
| Değişken | Varsayılan | Açıklama |
| -------------------------- | --------------------------- | ------------------------------------------------------------- |
| `PORT` | `20128` | HTTP dinleme portu (Pano ve API aynı süreci paylaşır). |
| `HOST` / `HOSTNAME` | `0.0.0.0` | Ağ bağlama adresi (tüm arayüzleri dinler). |
| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | OAuth geri çağırma URL'leri ve istemci yönlendirmeleri için. |
| `RATE_LIMIT_AUTO_ENABLE` | `true` | Sağlayıcı başına hız sınırlamasını otomatik etkinleştirir. |
| `RATE_LIMIT_MAX_WAIT_MS` | `30000` | Hız sınırı kuyruğunda maksimum bekleme süresi (ms). |

View File

@@ -1,67 +1,65 @@
# OmniRoute Auto-Combo Engine (Türkçe)
---
title: "OmniRoute Auto-Combo Motoru"
version: 3.8.50
lastUpdated: 2026-08-23
---
🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇧🇩 [bn](../../bn/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇮🇷 [fa](../../fa/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇮🇳 [gu](../../gu/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇮🇳 [hi](../../hi/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇮🇳 [mr](../../mr/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇰🇪 [sw](../../sw/docs/AUTO-COMBO.md) · 🇮🇳 [ta](../../ta/docs/AUTO-COMBO.md) · 🇮🇳 [te](../../te/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇹🇷 [tr](../../tr/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇵🇰 [ur](../../ur/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md)
# OmniRoute Auto-Combo Motoru (Türkçe)
🌐 **Languages:** 🇺🇸 [English](../../../../docs/routing/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/routing/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/routing/AUTO-COMBO.md) · 🇧🇩 [bn](../../bn/docs/routing/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/routing/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/routing/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/routing/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/routing/AUTO-COMBO.md) · 🇮🇷 [fa](../../fa/docs/routing/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/routing/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/routing/AUTO-COMBO.md) · 🇮🇳 [gu](../../gu/docs/routing/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/routing/AUTO-COMBO.md) · 🇮🇳 [hi](../../hi/docs/routing/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/routing/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/routing/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/routing/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/routing/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/routing/AUTO-COMBO.md) · 🇮🇳 [mr](../../mr/docs/routing/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/routing/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/routing/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/routing/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/routing/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/routing/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/routing/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/routing/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/routing/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/routing/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/routing/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/routing/AUTO-COMBO.md) · 🇰🇪 [sw](../../sw/docs/routing/AUTO-COMBO.md) · 🇮🇳 [ta](../../ta/docs/routing/AUTO-COMBO.md) · 🇮🇳 [te](../../te/docs/routing/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/routing/AUTO-COMBO.md) · 🇹🇷 [tr](../../tr/docs/routing/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/routing/AUTO-COMBO.md) · 🇵🇰 [ur](../../ur/docs/routing/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/routing/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/routing/AUTO-COMBO.md)
---
> Self-managing model chains with adaptive scoring
> Uyarlanabilir puanlama + sıfır yapılandırmalı otomatik yönlendirme ile kendi kendini yöneten model zincirleri
## How It Works
## Sıfır Yapılandırmalı Otomatik Yönlendirme (`auto/` Öneki)
The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
> **YENİ:** Kombo oluşturma gerektirmez. Herhangi bir istemcide doğrudan `auto/` önekini kullanın.
| Factor | Weight | Description |
| :--------- | :----- | :---------------------------------------------- |
| Quota | 0.20 | Remaining capacity [0..1] |
| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
| TaskFit | 0.10 | Model × task type fitness score |
| Stability | 0.10 | Low variance in latency/errors |
### Hızlı Örnekler
## Mode Packs
| Model ID | Varyant | Davranış |
| -------------- | ------- | ------------------------------------------------------------------------ |
| `auto` | varsayılan | Tüm bağlı sağlayıcılar, LKGP stratejisi, dengeli ağırlıklar |
| `auto/coding` | coding | Kalite öncelikli ağırlıklar, kod üretimi için optimize |
| `auto/fast` | fast | Düşük gecikmeli ağırlıklı seçim |
| `auto/cheap` | cheap | Maliyet optimizasyonlu yönlendirme (en ucuz olan önce) |
| `auto/offline` | offline | En yüksek kota kullanılabilirliğine sahip sağlayıcıları tercih eder |
| `auto/smart` | smart | Kalite öncelikli + daha iyi model keşfi için %10 keşif oranı |
| `auto/lkgp` | lkgp | Açık LKGP (varsayılan `auto` ile aynı) |
| Pack | Focus | Key Weight |
| :---------------------- | :----------- | :--------------- |
| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
| 💰 **Cost Saver** | Economy | costInv: 0.40 |
| 🎯 **Quality First** | Best model | taskFit: 0.40 |
| 📡 **Offline Friendly** | Availability | quota: 0.40 |
### Kategori × Katman Birleşimi (`auto/<category>:<tier>`)
## Self-Healing
OpenRouter tarzı sonekler, **ne tür bir rota** (kategori) ile **nasıl optimize edileceğini** (katman) ayırır:
- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
- **Incident mode**: >50% OPEN → disable exploration, maximize stability
- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
- **Kategoriler** (aday havuzunu yeteneğe göre filtreler): `coding` · `reasoning` · `vision` · `chat` · `multimodal`.
- **Katmanlar** (puanlama ağırlıklarını seçer): `fast` · `cheap` · `reliable` · `free` / `pro`.
## Bandit Exploration
| Örnek | Çözümlendiği Rota |
| ---------------------- | ------------------------------------------------------- |
| `auto/coding:fast` | kodlama havuzu, düşük gecikmeli ağırlıklar |
| `auto/coding:cheap` | kodlama havuzu, maliyet optimizasyonlu |
| `auto/reasoning:pro` | yalnızca akıl yürütme/düşünme modelleri, premium katman |
| `auto/vision` | vision yetenekli modeller (dengeli ağırlıklar) |
| `auto/multimodal:free` | çok modlu modeller, yalnızca ücretsiz katman |
5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
---
## API
## 14 Faktörlü Auto-Combo Puanlama Matrisi
```bash
# Create auto-combo
curl -X POST http://localhost:20128/api/combos/auto \
-H "Content-Type: application/json" \
-d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
Auto-Combo motoru, her istek için aday sağlayıcıları **14 bağımsız faktör** üzerinden canlı olarak puanlar:
# List auto-combos
curl http://localhost:20128/api/combos/auto
```
## Task Fitness
30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
## Files
| File | Purpose |
| :------------------------------------------- | :------------------------------------ |
| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
| `src/app/api/combos/auto/route.ts` | REST API |
1. **Sağlık Durumu (Health):** Devre kesici durumu (KAPALI = 1.0, AÇIK = 0.0).
2. **Kalan Kota Oranı (Quota Remaining):** Mevcut kota penceresinde kalan yüzde.
3. **Kota Hacmi (Quota Headroom):** Kalan mutlak token veya istek miktarı.
4. **Maliyet Etkinliği (Cost):** Giriş/çıkış token başına katalog fiyatı ($).
5. **Gecikme (Latency):** p50/p95 geçmiş yanıt süresi (ms).
6. **Başarı Oranı (Success Rate):** Son 100 çağrıdaki 2xx HTTP yanıt oranı.
7. **Tazelik (Freshness):** Sağlayıcının son başarılı kullanımından bu yana geçen süre.
8. **LKGP Uyumu (Stickiness):** Son başarılı sağlayıcıya sadakat puanı.
9. **Hata Oranı Eğilimi (Error Rate Trend):** Son 5 dakikadaki 429/5xx hata sıklığı.
10. **Kota Sıfırlanma Yakınlığı (Reset Proximity):** Kota sıfırlanmasına kalan süre.
11. **Önbellek Uyumu (Cache Affinity):** İstem önbelleğini (prompt cache) tutan bağlantıya öncelik verme.
12. **Model Yetenek Uyumu (Capability Match):** Vision, araç çağırma, JSON şema desteği.
13. **Bandit Keşif Payı (Exploration Boost):** Daha iyi modelleri keşfetmek için rastgele deneme ağırlığı.
14. **Yük Dengeleme (Load Distribution):** P2C (power of two choices) ile eşzamanlı istek dağılımı.

View File

@@ -6866,7 +6866,11 @@ paths:
Returns a structured JSON catalog parsed from this `openapi.yaml`,
including info, servers, tags, schemas, and a flat list of endpoints
(method, path, tags, summary, security, parameters, responses).
Used by the in-app API explorer.
Used by the in-app API explorer. When `requireLogin` is enabled, this
management endpoint requires an authenticated dashboard session;
otherwise it is available without authentication.
security:
- ManagementSessionAuth: []
responses:
"200":
description: Parsed OpenAPI catalog
@@ -6920,6 +6924,10 @@ paths:
type: string
"404":
description: openapi.yaml file not found on disk
"401":
$ref: "#/components/responses/ManagementAuthenticationRequired"
"403":
$ref: "#/components/responses/ManagementInvalidToken"
"500":
description: Failed to parse OpenAPI spec

View File

@@ -1,7 +1,7 @@
---
title: "Database Schema & Operations Guide"
version: 3.8.40
lastUpdated: 2026-06-28
version: 3.8.50
lastUpdated: 2026-08-23
---
# Database Schema & Operations Guide
@@ -43,12 +43,17 @@ For **single-user, single-instance** deployments (the primary OmniRoute use case
db.pragma("journal_mode = WAL");
db.pragma("busy_timeout = 2000");
db.pragma("synchronous = NORMAL");
// Settings > System & Storage > Cache Size is applied as KiB.
db.pragma("cache_size = -16384");
db.pragma(`cache_size = -${DEFAULT_DATABASE_SETTINGS.optimization.cacheSize}`);
```
WAL allows **concurrent reads** during writes — important for the dashboard, which queries while requests are being recorded.
The default cache size is **65,536 KiB (64 MiB)**. SQLite interprets a negative
`cache_size` as an approximate upper bound in KiB and allocates pages on demand.
**Settings > System & Storage > Cache Size** accepts integer values from **1 to
1,000,000 KiB**; saving the setting applies it to the live database connection,
and OmniRoute restores the persisted value at startup.
---
## Database Location

Some files were not shown because too many files have changed in this diff Show More