Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
5c5ed39
feat(dashboard): render log payloads as a collapsible JSON tree
hartmark Aug 24, 2026
5cb3b6b
fix(dashboard): render event-stream JSON as trees, fix call-id/conver…
hartmark Aug 24, 2026
d0389f3
feat(dashboard): add collapse/expand-depth controls to JSON tree boxes
hartmark Aug 24, 2026
2083634
feat(dashboard): per-section expand levels + timestamp hover tooltips
hartmark Aug 24, 2026
fbd54b5
fix(dashboard): stop expand-state reset on individual node toggle, sc…
hartmark Aug 24, 2026
b480777
refactor(dashboard): replace react-json-view-lite with react18-json-view
hartmark Aug 25, 2026
c365159
fix(i18n): add missing pt-BR translations for collapsible JSON tree v…
hartmark Aug 28, 2026
95f0e3e
merge(release/v3.8.51): refresh onto 3b752f9d4cbb
hartmark Aug 29, 2026
87b3bdf
fix(resilience): lock permanently retired models instead of short bac…
turbolego Aug 29, 2026
91f9a01
fix(resilience): stop hammering permanently-moved endpoints and billi…
turbolego Aug 29, 2026
d887937
fix(combo): lock GitHub models rejected as "not supported" for future…
turbolego Aug 29, 2026
c705147
docs(i18n): finish Freepik → Magnific rebrand in locale strings and R…
turbolego Aug 29, 2026
d2ad71c
fix(kie): route flux/kontext to its dedicated endpoint, not the Marke…
diegosouzapw Aug 29, 2026
674cc5f
fix(db): rate-limit Arena ELO fetch-failure warnings on repeated time…
diegosouzapw Aug 29, 2026
fb9cbe9
fix(ci): pass --pass-on-unpruned-suppressions in run-eslint-json.mjs …
diegosouzapw Aug 29, 2026
71093ed
fix(codex): keep parallel_tool_calls:false on translated Responses Li…
diegosouzapw Aug 29, 2026
322b218
fix(cli): drop the never-produced dist/index.cjs requirement from pre…
diegosouzapw Aug 29, 2026
bd04bb9
fix(sse): set X-OmniRoute-Selected-Connection-Id on successful combo …
diegosouzapw Aug 29, 2026
02ba573
fix(providers): scope Antigravity mitmAlias tier ids to the safe stat…
diegosouzapw Aug 29, 2026
e6de61f
fix(sse): stop the auto-combo candidates inspector from dropping bloc…
diegosouzapw Aug 29, 2026
c4bd8b8
fix(release): electron lockfile resync, build_ref, curated notes and …
diegosouzapw Aug 29, 2026
38e2616
fix(ci): stop hosted docker-publish OOM and unpaint Build (advisory) …
diegosouzapw Aug 29, 2026
47f7e5a
fix(release): the packaged-app smoke verifies the database opened, no…
diegosouzapw Aug 29, 2026
a9aee94
docs(ops): the .113 heavy-build ceiling is one runner, not two (#12048)
diegosouzapw Aug 29, 2026
9ec4d39
fix(ci): webpack for docker-publish even on omni-build (#12050)
diegosouzapw Aug 29, 2026
c8dc982
fix(ci): drop the stale ESLint cache restore-keys fallback from ci.ym…
diegosouzapw Aug 29, 2026
c9b1c12
fix(db): include local no-API-key providers in Qdrant embedding-model…
diegosouzapw Aug 29, 2026
d32c76f
fix(config): correct Hermes-4-405B display label from 7B to 405B (#11…
diegosouzapw Aug 29, 2026
065d998
fix(cli): update flow now says whether the running process needs a re…
diegosouzapw Aug 29, 2026
34e2f84
feat(api): explicit model exposure allow/deny list for /v1/models (#1…
diegosouzapw Aug 29, 2026
2b8d3a8
fix(radar): restore D12 public boundary (#12057)
diegosouzapw Aug 29, 2026
3b00535
feat(guardrails): enforce video transcript provenance, budgets and re…
diegosouzapw Aug 29, 2026
60dc242
feat(video): derive embedded subtitle provenance in the protected bro…
diegosouzapw Aug 29, 2026
ef66896
test(video): freeze FU-07/FU-09 promotion-evidence manifest, aggregat…
diegosouzapw Aug 29, 2026
f30e5b2
feat(video): connect tenant-bound drill-down lifecycle and multiresol…
diegosouzapw Aug 29, 2026
e8b2cd2
docs(video): clarify Video Bridge transcript provenance is caller-dec…
diegosouzapw Aug 29, 2026
5fcd39b
feat(video): orchestrate Audio Bridge STT with one-download budgets (…
diegosouzapw Aug 29, 2026
36b7920
refactor(video): extract a Video Bridge pipeline with explicit ports …
diegosouzapw Aug 29, 2026
55e33f3
fix(sse): default crash-guard logger to console.warn, not console (#1…
HouMinXi Aug 29, 2026
5698769
fix(cli): support --base-url alongside --endpoint in nodes subcommand…
HouMinXi Aug 29, 2026
d3420d2
fix(admission): exclude reclaimable page cache from the cgroup pressu…
HouMinXi Aug 29, 2026
38e2baa
fix(resilience): clear persisted LKGP pin on target exhaustion and sk…
HouMinXi Aug 29, 2026
aa861a8
fix(barrel): migrate src/app/ off the @/lib/localDb barrel import (#1…
jonlwheat2-gif Aug 30, 2026
2463781
fix(barrel): migrate src/lib/ off the localDb barrel to direct db imp…
jonlwheat2-gif Aug 30, 2026
38a2966
URGENT fix(build): route ChatGPT Web MCP bundle through runBuildTool …
jonlwheat2-gif Aug 30, 2026
4e11887
fix(barrel): migrate open-sse, src/shared, src/sse, src/models, src/d…
jonlwheat2-gif Aug 30, 2026
50bc8ab
fix(barrel): delete the @/lib/localDb barrel — every consumer migrate…
jonlwheat2-gif Aug 30, 2026
2ec24e7
fix(core): resolve DB init race condition and reasoning translation (…
raheemuddin786 Aug 30, 2026
da678bd
feat(config): add support for runtime system prompt configuration and…
raheemuddin786 Aug 30, 2026
92574de
fix(chat): preserve unstripped model string for passthrough provider …
raheemuddin786 Aug 30, 2026
d26fe03
feat(routing): add relayMode for schema-locked context handoffs (#11839)
raheemuddin786 Aug 30, 2026
47ea113
fix(ci): reconcile release test contract drift (#12082)
backryun Aug 30, 2026
49827c1
fix(dev): bound webpack and Tailwind scans (#12075)
backryun Aug 30, 2026
a1d6ff5
fix(api): preserve caller-provided X-Correlation-Id on chat completio…
aniruddhaadak80 Aug 30, 2026
55691e0
fix(usage): allow quota refresh for FREE lease-reserved connections (…
TheDemonTuan Aug 30, 2026
faebf6d
fix(shared): block cloud-metadata hosts under default remote-image gu…
santosraju99-hub Aug 30, 2026
c2c97af
ci: add API route TypeScript regression gate (#11705)
Sabeekhann Aug 30, 2026
d4835d1
resync #11703 onto updated release/v3.8.51
diegosouzapw Aug 30, 2026
ef461f4
fix duplicate deps + rebaseline file-size for #11703 resync
diegosouzapw Aug 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
36 changes: 36 additions & 0 deletions .github/workflows/api-route-typecheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: API Route Typecheck

on:
pull_request:
branches:
- main
- "release/**"
types: [opened, synchronize, reopened, ready_for_review]
push:
branches: [main]
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
api-typecheck:
name: API Route Typecheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: "24"
cache: npm
- uses: ./.github/actions/npm-ci-retry
- name: Reject new API-route TypeScript diagnostics
run: node scripts/check/check-api-typecheck.mjs
- name: API typecheck gate unit tests
run: node --import tsx/esm --test tests/unit/build/check-api-typecheck.test.ts
20 changes: 13 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,11 @@ jobs:
.eslintcache
.eslintcache-complexity
key: eslint-${{ runner.os }}-${{ hashFiles('eslint.config.mjs', 'eslint.complexity-ratchets.config.mjs', 'config/quality/eslint-suppressions.json', 'package-lock.json') }}
restore-keys: |
eslint-${{ runner.os }}-
# No restore-keys fallback on purpose (#11600, P-II.1 of the v3.8.50 postmortem): a
# cache built under a different suppressions file / lint config / lockfile reports
# stale per-file verdicts, which is exactly how 215 pre-existing errors stayed
# invisible for a whole cycle. Exact key or a cold full lint (~13 min) — never a
# partial cache from another configuration.
# Single ESLint inventory (JSON) — quality-gate reuses the artifact instead of
# a second cold full-tree pass for eslintWarnings ratchet counts.
- name: ESLint (JSON report)
Expand Down Expand Up @@ -209,8 +212,11 @@ jobs:
.eslintcache
.eslintcache-complexity
key: eslint-${{ runner.os }}-${{ hashFiles('eslint.config.mjs', 'eslint.complexity-ratchets.config.mjs', 'config/quality/eslint-suppressions.json', 'package-lock.json') }}
restore-keys: |
eslint-${{ runner.os }}-
# No restore-keys fallback on purpose (#11600, P-II.1 of the v3.8.50 postmortem): a
# cache built under a different suppressions file / lint config / lockfile reports
# stale per-file verdicts, which is exactly how 215 pre-existing errors stayed
# invisible for a whole cycle. Exact key or a cold full lint (~13 min) — never a
# partial cache from another configuration.
# Coverage mergeada (coverage-summary.json) p/ o ratchet de cobertura.
# continue-on-error: o artifact pode não existir se a job test-coverage foi
# SKIPPED (shard flaky). Nesse caso collect-metrics pula coverage.* (ausente sem
Expand Down Expand Up @@ -621,9 +627,9 @@ jobs:
# 13:50Z the kernel OOM-killed main's build while a PR build ran beside it
# (five Build jobs had been queued by a burst of PRs). Two lanes: main keeps
# its own so a release is never queued behind PR traffic; PR builds serialize
# among themselves. GitHub keeps one running + one pending per group and
# CANCELS older pendings — a cancelled PR build is re-runnable; a dead main
# build costs the publish its artefact and a 40-minute rebuild that OOMs.
# among themselves. docker-publish.yml's amd64 leg joins `heavy-build-main`
# so a :next image build waits beside this artefact instead of becoming the
# third heavy (#11976). GitHub keeps one running + one pending per group.
concurrency:
group: heavy-build-${{ github.ref == 'refs/heads/main' && 'main' || 'pr' }}
cancel-in-progress: false
Expand Down
39 changes: 36 additions & 3 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ on:
type: boolean
default: false

# One publish per ref. A merge storm used to fan out 8 concurrent hosted builds,
# every one OOM-killing `npm run build` inside BuildKit (#11976). The :next
# channel only needs the newest SHA; cancel-in-progress is the same pattern as
# quality.yml / nightly-release-green.
concurrency:
group: docker-publish-${{ github.ref }}
cancel-in-progress: true

# Least-privilege default: read-only at the top level; the build and merge jobs that
# push to GHCR grant packages: write themselves (Scorecard TokenPermissions).
permissions:
Expand Down Expand Up @@ -118,7 +126,23 @@ jobs:
name: Build Docker (${{ matrix.platform }})
needs: prepare
if: needs.prepare.outputs.skip != 'true'
runs-on: ${{ matrix.runner }}
# amd64: the .113 omni-build pool (31 GB / 32 cores, ONE listener since
# #12048). Hosted ubuntu-24.04 is ~7 GB and dies ResourceExhausted (#11976).
# Falls back to hosted when USE_VPS_RUNNER is off. arm64: no ARM box — stay
# on GitHub's ubuntu-24.04-arm.
# Webpack on BOTH arches: Turbopack on omniroute-113-6 hit
# TurbopackInternalError "there must be a path to a root" after 26 min
# (run 33253576569). The same tree's arm64 webpack build on hosted ARM
# succeeded (run 33264823398). Dockerfile already documents webpack as the
# Docker escape hatch (OMNIROUTE_USE_TURBOPACK=0).
runs-on: ${{ matrix.arch == 'amd64' && (vars.USE_VPS_RUNNER == 'true' && fromJSON('["self-hosted","omni-build"]') || 'ubuntu-24.04') || 'ubuntu-24.04-arm' }}
# Share the 1-slot omni-build ceiling (#12048) with ci.yml `Build` /
# npm-publish. Same group as main's Build so a :next publish waits beside
# the artefact instead of sitting next to it. arm64 is hosted — its own
# group, cancelled by the workflow-level concurrency.
concurrency:
group: ${{ matrix.arch == 'amd64' && 'heavy-build-main' || format('docker-publish-arm-{0}', github.ref) }}
cancel-in-progress: ${{ matrix.arch != 'amd64' }}
permissions:
contents: read
packages: write
Expand All @@ -127,10 +151,8 @@ jobs:
matrix:
include:
- platform: linux/amd64
runner: ubuntu-24.04
arch: amd64
- platform: linux/arm64
runner: ubuntu-24.04-arm
arch: arm64
env:
IMAGE_NAME: diegosouzapw/omniroute
Expand All @@ -143,6 +165,9 @@ jobs:
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/v{0}', inputs.version) || '' }}
fetch-depth: 0

- name: Assert Docker Engine
run: docker info

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4

Expand All @@ -166,6 +191,8 @@ jobs:
context: .
target: runner-base
platforms: ${{ matrix.platform }}
build-args: |
OMNIROUTE_USE_TURBOPACK=0
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
tags: |
${{ env.IMAGE_NAME }}
Expand All @@ -183,6 +210,8 @@ jobs:
context: .
target: runner-web
platforms: ${{ matrix.platform }}
build-args: |
OMNIROUTE_USE_TURBOPACK=0
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
tags: |
${{ env.IMAGE_NAME }}
Expand All @@ -208,6 +237,8 @@ jobs:
file: Dockerfile.bun
target: runner-base
platforms: ${{ matrix.platform }}
build-args: |
OMNIROUTE_USE_TURBOPACK=0
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
tags: |
${{ env.IMAGE_NAME }}
Expand All @@ -233,6 +264,8 @@ jobs:
file: Dockerfile.bun
target: runner-web
platforms: ${{ matrix.platform }}
build-args: |
OMNIROUTE_USE_TURBOPACK=0
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
tags: |
${{ env.IMAGE_NAME }}
Expand Down
17 changes: 8 additions & 9 deletions .github/workflows/electron-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ on:
push:
tags:
- "v*"
# A dispatch builds the ref it is dispatched ON (`gh workflow run … --ref v3.8.50` rebuilds
# that tag; `--ref main` builds the repaired line). The ref is deliberately NOT an input:
# CodeQL flags an input-controlled checkout next to the npm cache on the default branch as
# cache poisoning (actions/cache-poisoning/poisonable-step), and `github.ref` is trusted.
workflow_dispatch:
inputs:
version:
Expand Down Expand Up @@ -81,9 +85,6 @@ jobs:
- uses: actions/checkout@v7
with:
persist-credentials: false
# workflow_dispatch: build the tag being (re)built, not the dispatching branch. On a
# tag push this resolves to the same commit.
ref: ${{ needs.validate.outputs.version }}
- name: Setup Node
uses: actions/setup-node@v7
with:
Expand Down Expand Up @@ -169,9 +170,6 @@ jobs:
- uses: actions/checkout@v7
with:
persist-credentials: false
# workflow_dispatch: build the tag being (re)built, not the dispatching branch. On a
# tag push this resolves to the same commit.
ref: ${{ needs.validate.outputs.version }}
- name: Setup Node
uses: actions/setup-node@v7
with:
Expand Down Expand Up @@ -358,8 +356,6 @@ jobs:
with:
persist-credentials: false
fetch-depth: 0
# Source archives + SBOM come from the tag being released, not the dispatching branch.
ref: ${{ needs.validate.outputs.version }}

# `merge-multiple` is deliberately OFF. It resolves same-name collisions by ARRIVAL
# ORDER, and the two macOS jobs each emit their own `latest-mac.yml` listing only their
Expand Down Expand Up @@ -417,7 +413,10 @@ jobs:
tag_name: ${{ needs.validate.outputs.version }}
draft: false
prerelease: false
generate_release_notes: true
# Only on the tag push. A re-attach dispatch runs against a release whose curated
# notes already exist, and `true` APPENDS GitHub's auto-generated "What's Changed"
# block to them (v3.8.50, run 33238093090: +1,416 chars on a 121 KB body).
generate_release_notes: ${{ github.event_name != 'workflow_dispatch' }}
fail_on_unmatched_files: false
files: |
release-assets/*.dmg
Expand Down
15 changes: 12 additions & 3 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,20 @@ jobs:
if-no-files-found: error

- name: Attach SBOM to GitHub Release
if: steps.resolve.outputs.skip != 'true' && github.event_name == 'release'
# Not only on the `release` event: the v3.8.50 package shipped through a
# workflow_dispatch (staged publish, 11 attempts) and this step was skipped, so the
# GitHub Release carried no SBOM until it was attached by hand from the run's
# `sbom-npm` artifact. Attach whenever a release for the published tag exists.
if: steps.resolve.outputs.skip != 'true' && (github.event_name == 'release' || github.event_name == 'workflow_dispatch')
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
run: gh release upload "$TAG" sbom-npm.cdx.json --clobber
TAG: ${{ github.event_name == 'release' && github.ref_name || format('v{0}', inputs.version) }}
run: |
if ! gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
echo "::notice::no GitHub Release for $TAG yet — SBOM stays on the sbom-npm workflow artifact"
exit 0
fi
gh release upload "$TAG" sbom-npm.cdx.json --repo "$GITHUB_REPOSITORY" --clobber

# WS1.2/WS1.3 (#7065 class): the artifact that is about to be published must
# BOOT. build:cli already assembled dist/ above; this packs+installs+boots the
Expand Down
11 changes: 10 additions & 1 deletion .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,16 @@ jobs:
# 2026-08-14: 72 of the last 100 PRs into release/** came from forks, so the fork case is
# the majority of the traffic, not the exception — this job earns its place, it just should
# not duplicate build.yml for the own-origin 28%.
if: ${{ github.event_name != 'pull_request' || ((github.event.pull_request.draft == false || startsWith(github.head_ref, 'mergify/merge-queue/')) && needs.changes.outputs.code == 'true' && github.event.pull_request.head.repo.full_name != github.repository) }}
# Disabled 2026-08-29 (#11976 follow-up). `continue-on-error: true` still
# reports a GitHub check FAILURE, so every fork PR into release/** was born
# with a red "Build (advisory)" even when every required gate was green
# (sweep-reds, 41 PRs). Hosted ubuntu-latest cannot finish `npm run build`
# on this tree — VM shutdown ~6 min in, same class as build.yml going
# workflow_dispatch-only in #11962. Pre-merge build signal for release/**
# is nightly-release-green (omni-build); for main it is ci.yml `Build`.
# Restore this job when a runner that actually fits the tree is wired here.
# Bare `false` (not `${{ false }}`) — zizmor obfuscation flags the expression form.
if: false
# PINNED to hosted — this was the last job in THIS workflow still on the USE_VPS_RUNNER
# switch (ci.yml's Build, nightly-release-green and npm-publish keep it, so the variable
# stays meaningful), and with USE_VPS_RUNNER=true it produced NO signal at all here.
Expand Down
8 changes: 3 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,7 @@ When creating _any_ validation tests or one-off logic scripts, default to `scrip
### Database

- **Always** go through `src/lib/db/` domain modules — **never** write raw SQL in routes or handlers
- **Never** add logic to `src/lib/localDb.ts` (re-export layer only)
- **Never** barrel-import from `localDb.ts` — import specific `db/` modules instead
- **Never** barrel-import from `localDb.ts` — import specific `src/lib/db/*` modules
- DB singleton: `getDbInstance()` from `src/lib/db/core.ts` (WAL journaling)
- Migrations: `src/lib/db/migrations/` — versioned SQL files, idempotent, run in transactions

Expand Down Expand Up @@ -355,8 +354,7 @@ Documentation must describe verified behavior, not plausible behavior.
1. Create `src/lib/db/yourModule.ts` — import `getDbInstance` from `./core.ts`
2. Export CRUD functions for your domain table(s)
3. Add migration in `src/lib/db/migrations/` if new tables needed
4. Re-export from `src/lib/localDb.ts` (add to the re-export list only)
5. Write tests
4. Write tests

### Adding a New MCP Tool

Expand Down Expand Up @@ -668,7 +666,7 @@ the stale-enforcement added in Fase 6A.3.
## Hard Rules

1. Never commit secrets or credentials
2. Never add logic to `localDb.ts`
2. Never barrel-import from `localDb.ts` — import specific `src/lib/db/*` modules
3. Never use `eval()` / `new Function()` / implied eval
4. Never commit directly to `main`
5. Never write raw SQL in routes — use `src/lib/db/` modules
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ the current catalog at **[radar.omniroute.online/planos](https://radar.omniroute
- **🧠 Memory you control** — off by default, opt-in int8 vector quantization + typed decay, per-request `x-omniroute-no-memory`. → [Memory](docs/frameworks/MEMORY.md)
- **🛡️ Security** — prompt-injection guard on every LLM route (red-team suite), opt-in credential-masking guardrail (redacts leaked API keys/secrets in both directions), free DuckDuckGo last-resort web search, and an optional OIDC login gate for the dashboard (password login always stays available). → [Guardrails](docs/security/GUARDRAILS.md)
- **🖼️ New endpoints** — `/v1/ocr` (Mistral OCR) and `/v1/audio/translations` (Whisper-style) round out the media surface. → [API Reference](docs/reference/API_REFERENCE.md)
- **🎨 Image / video / audio generation** — one API for media: xAI Grok Imagine & Novita AI video, ComfyUI, Freepik, Adobe Firefly, Segmind, and speech providers such as ElevenLabs. → [API Reference](docs/reference/API_REFERENCE.md)
- **🎨 Image / video / audio generation** — one API for media: xAI Grok Imagine & Novita AI video, ComfyUI, Magnific, Adobe Firefly, Segmind, and speech providers such as ElevenLabs. → [API Reference](docs/reference/API_REFERENCE.md)
- **🌍 Deployment & ops** — reverse-proxy `basePath`, browser-language auto-detect, per-key device tracking, root-less MITM trust, zh-TW localization. → [Environment](docs/reference/ENVIRONMENT.md)
- **🤝 More providers & agents** — Cursor Cloud Agent, Grok Build (xAI) with browser + OAuth login, Ollama first-class card, Claude Opus 5 & Sonnet 5, Kimi official partnership (Code/Web/Moonshot), Zed, Requesty, SenseNova, Yuanbao, Agnes AI… and a refreshed **351-provider catalog**. → [Providers](docs/reference/PROVIDER_REFERENCE.md)
- **📡 Routing transparency** — every response carries an `X-OmniRoute-Decision` header naming the strategy/provider/latency that served it, a new `cache-optimized` combo strategy + Auto-Combo `cacheAffinity` factor route repeat requests back to the connection holding the cached prefix, and a read-only `/v1/auto-combo/{channel}/candidates` endpoint exposes an `auto/*` channel's live candidate pool. → [Auto-Combo](docs/routing/AUTO-COMBO.md)
Expand Down
Loading
Loading