Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
064157d
fix(resilience): drain heavyweight SSE on SIGTERM (#11015)
RaviTharuma Aug 21, 2026
742ccb9
fix(ci): register oauth-autoimport-local-only test in stryker tap.tes…
hartmark Aug 22, 2026
9629693
fix(providers): filter Perplexity model import to the Sonar family (#…
diegosouzapw Aug 22, 2026
d91238b
fix(install): make ONNX chain optional for Android/Termux installs (#…
diegosouzapw Aug 22, 2026
da490a7
fix(sse): resume stream recovery after a completed tool call (#11109)
maxmad64bis Aug 22, 2026
d9b3ce2
test(stream): direct coverage + comment for splitConcatenatedToolCall…
maxmad64bis Aug 22, 2026
02a078e
fix(sse): default summary on freshly-built Chat->Responses reasoning …
maxmad64bis Aug 22, 2026
b44f22a
fix(webhooks): followup ghost-event dispatcher tests + vi i18n (#1105…
maxmad64bis Aug 22, 2026
efc7134
fix(registry): restore models[0] default + guards; note muse-spark ov…
maxmad64bis Aug 22, 2026
78b4082
fix(autopilot): show real suggestion count and link dashboard (#11102)
maxmad64bis Aug 22, 2026
d021423
fix(sse): default summary + strip malformed id on kept Responses inpu…
maxmad64bis Aug 22, 2026
f3b190b
fix(providers): reject silent validation degradation with 400 and rej…
maxmad64bis Aug 22, 2026
84c9dfd
fix(config-audit): persist config audit log to SQLite with retention …
maxmad64bis Aug 22, 2026
c89fc6b
feat(providers): let operators add per-provider error rules via setti…
maxmad64bis Aug 22, 2026
1dd0173
fix(sse): assign a stable index/id to parallel function_call items in…
maxmad64bis Aug 22, 2026
5631e91
fix(providers): learn reasoning_effort capability from upstream 4xx i…
maxmad64bis Aug 22, 2026
dae3a72
fix(i18n): translate providers.harImport* keys into Vietnamese (#1106…
hartmark Aug 22, 2026
a51b8ba
fix(cline): use valid modelType/model format for Cline provider model…
rqzbeh Aug 22, 2026
3157e8a
fix(providers): require API key for Pollinations and fix optional key…
rqzbeh Aug 22, 2026
9a67185
fix(cli): support OpenCode V2 config format in setup-opencode (#11070…
rqzbeh Aug 22, 2026
50fc0d7
fix(resilience): keep Ollama model-not-found failures scoped to conne…
rqzbeh Aug 22, 2026
4220c81
fix(resilience): include RFC1918, CGNAT, and mDNS hosts in isLocalPro…
rqzbeh Aug 22, 2026
367ae2f
fix(search): enforce blockedProviders setting on search endpoint (#11…
rqzbeh Aug 22, 2026
b2509bc
fix(release): drain v3.8.50 base-reds — getTokenLimit contract, vi i1…
diegosouzapw Aug 22, 2026
aa12873
fix(providers): remove Hack Club AI provider (#11118) (#11123)
rqzbeh Aug 22, 2026
56540f2
fix(api): save call logs and add endpoint fallback for local rerank p…
AndrianBalanescu Aug 22, 2026
80d931a
fix(logs): apply filter predicates to merged in-memory call-log rows …
AndrianBalanescu Aug 22, 2026
e15af18
fix(kimi): point kimi-web to international www.kimi.ai (#11045)
MeRezaRezaei Aug 22, 2026
7360ca4
feat(redis): add configurable key namespace prefix (#11042)
MeRezaRezaei Aug 22, 2026
445121f
docs: DEFAULT_RATE_LIMIT_PER_DAY unset is unlimited (#11031)
Prajeeth-12 Aug 22, 2026
c19c73f
fix(claude): restore canonical tool names so Claude Code accepts tool…
linhdmn Aug 22, 2026
5818cfb
docs(cli): update opencode.ts JSDoc to reflect 128k context fallback …
rqzbeh Aug 22, 2026
64b7389
fix(tests): update translate-path golden snapshot and docs for hailuo…
rqzbeh Aug 22, 2026
d3ac1a6
refactor(dashboard): mirror check button disable state in AddApiKeyMo…
rqzbeh Aug 22, 2026
ec6010f
fix(cli): resolve blank device code and undefined verification URL in…
rqzbeh Aug 22, 2026
805252a
feat(mcp): implement dynamic runtime tool schema plumbing for blocked…
rqzbeh Aug 22, 2026
7246e5a
fix(bun): update Dockerfile.bun entrypoint and native bun:sqlite inst…
rqzbeh Aug 22, 2026
de5e237
feat(ci): publish Bun container images (-bun and -web-bun) in Docker …
rqzbeh Aug 22, 2026
2edb7a1
fix(dashboard): keep the provider registry out of node:net (#11122) (…
yourspraveen Aug 22, 2026
ce66d31
fix(quality): drain v3.8.50 base-reds — doc counts + orphan uncloseai…
yourspraveen Aug 22, 2026
92ef3c7
fix(resilience): honor shared-registry passthrough providers (#11071)…
yourspraveen Aug 22, 2026
f387575
fix(memory): treat TokenRouter as system-must-be-first (live HTTP 400…
ggdayup Aug 23, 2026
b384455
fix(api): refuse creating a routing combo without any model (#11162)
maxmad64bis Aug 23, 2026
1058426
fix(executors): rotate on upstream 400 empty-body rejections (opencod…
maxmad64bis Aug 23, 2026
60f25ef
fix(sse): merge purify_history compression notice into the leading sy…
ggdayup Aug 23, 2026
80b8d2a
fix(sse): resume stream recovery after a clean stop with reasoning-on…
maxmad64bis Aug 23, 2026
62ab93d
fix(sse): reject a low-overlap stream-recovery continuation instead o…
maxmad64bis Aug 23, 2026
eb9fa33
feat(api): structured ?format=json for the self-service usage endpoin…
diegosouzapw Aug 23, 2026
3ef54fc
feat(api): return every connection's snapshot under providers[] in om…
diegosouzapw Aug 23, 2026
eb57973
feat(dashboard): add CheaperInference sponsor banner and route banner…
diegosouzapw Aug 23, 2026
d888f1a
fix(combo): accept SSE comment lines (e.g. OpenRouter keep-alives) in…
asorourx Aug 23, 2026
e73ab00
fix(codex): make remote compaction V2 complete reliably (#11041)
jackjinke Aug 23, 2026
43ef7db
board #11020
hartmark Aug 23, 2026
4615880
chore(quality): freeze chatBodyAdmission at 1009 with annotation (#11…
hartmark Aug 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ DISABLE_SQLITE_AUTO_BACKUP=false
# Used by: src/shared/utils/rateLimiter.ts
# Example: redis://localhost:6379 (or redis://redis:6379 in Docker)
# REDIS_URL=redis://localhost:6379
# Namespace prefix for ALL OmniRoute Redis keys (rate limiter + auth cache +
# quota store). Prevents key collisions when OmniRoute shares a Redis instance
# with other apps (e.g. on 127.0.0.1:6379). Default when unset: omniroute:
# REDIS_KEY_PREFIX=omniroute:
# Host interface docker-compose publishes the Redis sidecar on.
# Default: 127.0.0.1 (loopback only). The compose Redis runs WITHOUT
# `requirepass`, and app containers reach it over the compose network
Expand Down Expand Up @@ -372,9 +376,8 @@ ALLOW_API_KEY_REVEAL=false
# NO_LOG_API_KEY_IDS=key_abc123,key_def456

# Fallback per-day request budget applied to API keys whose `rate_limits`
# column is null. Default (unset/empty/malformed) preserves the legacy
# 1000/day, 5000/week, 20000/month windows so existing deployments do not
# silently lose rate limiting on upgrade.
# column is null. Default (unset/empty) is unlimited (no implicit caps).
# Malformed values preserve the legacy 1000/day, 5000/week, 20000/month windows.
# Set explicitly to "0" to opt out entirely (unlimited fallback). Any
# positive integer N enables N/day, 5N/week, 20N/month.
# Used by: src/shared/utils/apiKeyPolicy.ts — checkRateLimit() fallback.
Expand Down
76 changes: 75 additions & 1 deletion .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,55 @@ jobs:
env:
DOCKER_BUILDKIT_INLINE_CACHE: 1

- name: Build and push BUN base platform image by digest
id: build-bun-base
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
with:
context: .
file: Dockerfile.bun
target: runner-base
platforms: ${{ matrix.platform }}
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
tags: |
${{ env.IMAGE_NAME }}
${{ env.GHCR_IMAGE_NAME }}
cache-from: type=gha,scope=docker-bun-base-${{ matrix.arch }}
cache-to: type=gha,scope=docker-bun-base-${{ matrix.arch }},mode=max
no-cache: false
env:
DOCKER_BUILDKIT_INLINE_CACHE: 1

- name: Build and push BUN web platform image by digest
id: build-bun-web
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
with:
context: .
file: Dockerfile.bun
target: runner-web
platforms: ${{ matrix.platform }}
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
tags: |
${{ env.IMAGE_NAME }}
${{ env.GHCR_IMAGE_NAME }}
cache-from: type=gha,scope=docker-bun-web-${{ matrix.arch }}
cache-to: type=gha,scope=docker-bun-web-${{ matrix.arch }},mode=max
no-cache: false
env:
DOCKER_BUILDKIT_INLINE_CACHE: 1

- name: Export digests
env:
DIGEST_BASE: ${{ steps.build.outputs.digest }}
DIGEST_WEB: ${{ steps.build-web.outputs.digest }}
DIGEST_BUN_BASE: ${{ steps.build-bun-base.outputs.digest }}
DIGEST_BUN_WEB: ${{ steps.build-bun-web.outputs.digest }}
run: |
set -euo pipefail
mkdir -p /tmp/digests/base /tmp/digests/web
mkdir -p /tmp/digests/base /tmp/digests/web /tmp/digests/bun-base /tmp/digests/bun-web
touch "/tmp/digests/base/${DIGEST_BASE#sha256:}"
touch "/tmp/digests/web/${DIGEST_WEB#sha256:}"
touch "/tmp/digests/bun-base/${DIGEST_BUN_BASE#sha256:}"
touch "/tmp/digests/bun-web/${DIGEST_BUN_WEB#sha256:}"

- name: Upload base digests
uses: actions/upload-artifact@v7
Expand All @@ -209,6 +249,22 @@ jobs:
if-no-files-found: error
retention-days: 1

- name: Upload bun-base digests
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: digests-bun-base-${{ matrix.arch }}
path: /tmp/digests/bun-base/*
if-no-files-found: error
retention-days: 1

- name: Upload bun-web digests
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: digests-bun-web-${{ matrix.arch }}
path: /tmp/digests/bun-web/*
if-no-files-found: error
retention-days: 1

merge:
name: Publish multi-arch manifests
needs:
Expand Down Expand Up @@ -263,6 +319,20 @@ jobs:
path: /tmp/digests/web
merge-multiple: true

- name: Download bun-base digests
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
pattern: digests-bun-base-*
path: /tmp/digests/bun-base
merge-multiple: true

- name: Download bun-web digests
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
pattern: digests-bun-web-*
path: /tmp/digests/bun-web
merge-multiple: true

- name: Create Docker Hub manifest
run: |
set -euo pipefail
Expand All @@ -286,6 +356,8 @@ jobs:

create_manifest "${IMAGE_NAME}" "" /tmp/digests/base
create_manifest "${IMAGE_NAME}" "-web" /tmp/digests/web
create_manifest "${IMAGE_NAME}" "-bun" /tmp/digests/bun-base
create_manifest "${IMAGE_NAME}" "-web-bun" /tmp/digests/bun-web

- name: Create GHCR manifest
run: |
Expand All @@ -310,6 +382,8 @@ jobs:

create_manifest "${GHCR_IMAGE_NAME}" "" /tmp/digests/base
create_manifest "${GHCR_IMAGE_NAME}" "-web" /tmp/digests/web
create_manifest "${GHCR_IMAGE_NAME}" "-bun" /tmp/digests/bun-base
create_manifest "${GHCR_IMAGE_NAME}" "-web-bun" /tmp/digests/bun-web

- name: Inspect image
if: needs.prepare.outputs.version != 'main'
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Repository map and Reference Documentation sections below.
| Translators | `open-sse/translator/` | Format conversion (OpenAI↔Claude↔Gemini) |
| Transformer | `open-sse/transformer/` | Responses API ↔ Chat Completions |
| Services | `open-sse/services/` | Combo routing, rate limits, caching, etc |
| Database | `src/lib/db/` | SQLite domain modules (157 migrations) |
| Database | `src/lib/db/` | SQLite domain modules (159 migrations) |
| Domain/Policy | `src/domain/` | Policy engine, cost rules, fallback logic |
| MCP Server | `open-sse/mcp-server/` | 110 tools (44 canonical + memory/skill/GitHub/pool/gamification/plugin/Notion/Obsidian/local-corpus/RTK modules), 3 transports (stdio / SSE / Streamable HTTP), 33 scopes |
| A2A Server | `src/lib/a2a/` | JSON-RPC 2.0 agent protocol |
Expand Down
63 changes: 60 additions & 3 deletions Dockerfile.bun
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ ENV NODE_ENV=production
# Bun native Next.js build execution
RUN bun run --quiet build

# ── Runner stage (100% Bun Native Production Runtime) ──────────────────────
FROM oven/bun:1.3.14-slim AS runner
# ── Runner Base stage (100% Bun Native Production Runtime) ──────────────────
FROM oven/bun:1.3.14-slim AS runner-base

LABEL org.opencontainers.image.title="omniroute" \
org.opencontainers.image.description="Unified AI proxy — route any LLM through one endpoint (Bun Native)" \
Expand Down Expand Up @@ -86,4 +86,61 @@ EXPOSE 20128
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
CMD bun healthcheck.mjs || exit 1

ENTRYPOINT ["bun", "bin/omniroute.mjs", "serve", "--no-open"]
ENTRYPOINT ["bun", "dev/run-standalone.mjs"]

# ── Runner Web stage (Bun Native + Chromium/Playwright for Web providers) ───
FROM runner-base AS runner-web

USER root

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
chromium \
chromium-driver \
fonts-liberation \
libasound2t64 \
gconf-service \
libatk-bridge2.0-0 \
libatk1.0-0 \
libc6 \
libcairo2 \
libcups2 \
libdbus-1-3 \
libexpat1 \
libfontconfig1 \
libgbm1 \
libgcc-s1 \
libglib2.0-0 \
libgtk-3-0 \
libnspr4 \
libnss3 \
libpango-1.0-0 \
pangocairo-1.0-0 \
stdc++6 \
libx11-6 \
libx11-xcb1 \
libxcb1 \
libxcomposite1 \
libxcursor1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxi6 \
libxrandr2 \
libxrender1 \
libxss1 \
libxtst6 \
ca-certificates \
fonts-gargi \
fonts-ipafont-gothic \
fonts-kacst \
fonts-thai-tlwg \
fonts-wqy-zenhei \
&& rm -rf /var/lib/apt/lists/*

ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
ENV PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium

# Return to the base image non-root user after the apt install (mirrors the
# Node Dockerfile runner-web stage, which re-asserts USER node).
USER bun
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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. 348 providers. Never stop building — OmniRoute picks the cheapest one that works. Six pillars: Never hit limits (auto-fallback across 348 providers in milliseconds, zero downtime) · Save up to 95% tokens (RTK + Caveman stacked compression cuts 15–95%, ~89% avg on tool-heavy sessions) · $0 to start (90+ free tiers, 57 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. 348 providers. Never stop building — OmniRoute picks the cheapest one that works. Six pillars: Never hit limits (auto-fallback across 348 providers in milliseconds, zero downtime) · Save up to 95% tokens (RTK + Caveman stacked compression cuts 15–95%, ~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/>
Expand Down Expand Up @@ -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: **348 providers**, **90+ with a free tier**, **57 free forever**.
> The most complete catalog of any open-source router: **348 providers**, **90+ with a free tier**, **56 free forever**.

<div align="center">

Expand Down Expand Up @@ -1200,7 +1200,7 @@ Métricas de validação: 1002 vídeos rastreados · 7,069,190 visualizações c
<tr><td nowrap><b>Runtime</b></td><td>Node.js 22.x / 24.x LTS — <code>&gt;=22.22.2 &lt;23 || &gt;=24.0.0 &lt;27</code></td></tr>
<tr><td nowrap><b>Language</b></td><td>TypeScript 6.0 — <b>100% TypeScript</b> across <code>src/</code> and <code>open-sse/</code> (zero <code>any</code> in core since v2.0)</td></tr>
<tr><td nowrap><b>Framework</b></td><td>Next.js 16 + React 19 + Tailwind CSS 4</td></tr>
<tr><td nowrap><b>Database</b></td><td>better-sqlite3 (SQLite, WAL journaling) + LowDB (JSON legacy) — 120 domain modules, 157 migrations</td></tr>
<tr><td nowrap><b>Database</b></td><td>better-sqlite3 (SQLite, WAL journaling) + LowDB (JSON legacy) — 120 domain modules, 159 migrations</td></tr>
<tr><td nowrap><b>Memory</b></td><td>SQLite FTS5 full-text + int8-quantized vector embeddings, typed decay</td></tr>
<tr><td nowrap><b>Schemas</b></td><td>Zod 4 — MCP tool I/O validation + API contracts</td></tr>
<tr><td nowrap><b>Protocols</b></td><td>MCP (stdio / HTTP / SSE) + A2A v0.3 (JSON-RPC 2.0 + SSE)</td></tr>
Expand Down
6 changes: 6 additions & 0 deletions bin/cli/commands/combo.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,12 @@ export async function runComboCreateCommand(name, strategy = "priority", opts =
}

const models = Array.isArray(opts.models) ? opts.models : [];
if (!models.length) {
console.error(
"combo create requires at least one target. Pass --models <provider/model,...> and/or repeat --model <provider/model>."
);
return 1;
}

try {
return await withRuntime(async ({ kind, api, db }) => {
Expand Down
36 changes: 27 additions & 9 deletions bin/cli/commands/oauth.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -228,20 +228,38 @@ async function runSocialFlow(def, opts) {

async function runDeviceFlow(def, opts) {
const providerKey = resolveBackendKey(def.id);
const startRes = await apiFetch(`/api/providers/${providerKey}/auth/start`, {
...targetApiOptions(opts),
method: "POST",
});
let startRes = await apiFetch(`/api/oauth/${providerKey}/device-code`, targetApiOptions(opts));
if (!startRes.ok) {
startRes = await apiFetch(`/api/providers/${providerKey}/auth/start`, {
...targetApiOptions(opts),
method: "POST",
});
}
if (!startRes.ok) {
process.stderr.write(`Failed to start device flow: ${startRes.status}\n`);
process.exit(1);
}
const start = await startRes.json();
process.stdout.write(
`\nDevice code: ${start.userCode ?? start.user_code ?? ""}\nVisit: ${start.verificationUri ?? start.verification_uri}\n\n`
);
if (opts.browser !== false)
await openBrowser(start.verificationUri ?? start.verification_uri ?? "");
const userCode = start.userCode ?? start.user_code ?? "";
const verificationUri =
start.verificationUriComplete ??
start.verification_uri_complete ??
start.verificationUri ??
start.verification_uri ??
start.authUrl ??
start.url ??
"";

if (userCode) {
process.stdout.write(`\nDevice code: ${userCode}\nVisit: ${verificationUri}\n\n`);
} else if (verificationUri) {
process.stdout.write(`\nVisit: ${verificationUri}\n\n`);
} else {
process.stdout.write(`\nAuthorization URL not available\n\n`);
}

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;
Expand Down
1 change: 1 addition & 0 deletions changelog.d/features/11104-operator-error-rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **feat(providers):** let operators declare per-provider error rules through `settings.providerErrorRules` instead of patching the catalog — an operator-supplied rule for a provider is consulted before the built-in `providerRuleRegistry`, receives the raw error text, and has its declared scope/cooldown/reason actually honored end to end, for any provider (declaring the rule is the opt-in — no extra allowlist entry needed). Matches are plain case-insensitive substrings (never RegExp) and bounded to 50 rules to keep the hot path safe ([#11104](https://github.com/diegosouzapw/OmniRoute/pull/11104))
1 change: 1 addition & 0 deletions changelog.d/features/11190-usage-command-json.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **feat(api):** `/api/usage/om-usage` gains a structured form — `?format=json` returns the key's own usage as `ApiKeyUsageLimitStatus` + `UsageSnapshot` instead of `text/plain`. This is the surface a UI (the OmniCopilot panel) consumes to show a key holder their daily/weekly spend and quota reset. The route is self-service (the caller's own key, gated by `allowUsageCommand`), not the management surface; refusals come back as a discriminated `{ "allowed": false, "error": … }` so a UI can tell "not allowed" apart from "allowed but nothing cached yet". The endpoint was previously undocumented in `API_REFERENCE.md`; it now has a section ([#11190](https://github.com/diegosouzapw/OmniRoute/pull/11190))
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **feat(api):** `/api/usage/om-usage?format=json` now returns `providers[]` — every connection's quota snapshot, not just the single selected one — so a panel can render Codex / Claude / OpenCode side by side. The collector already gathered all of them; the single-pick `provider` field (kept) is a terminal presentation choice. Closes the per-connection gap from OmniCopilot #8 ([#11192](https://github.com/diegosouzapw/OmniRoute/pull/11192))
1 change: 1 addition & 0 deletions changelog.d/fixes/11015-shutdown-track-sse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **fix(resilience):** count heavyweight `/v1` admission leases in the SIGTERM drain and send `Retry-After` on shutdown 503s so Recreate no longer looks like an empty 502 ([#11015](https://github.com/diegosouzapw/OmniRoute/issues/11015)) — thanks @RaviTharuma
1 change: 1 addition & 0 deletions changelog.d/fixes/11060-perplexity-filter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- fix(providers): filter Perplexity model import to the Sonar family so Agent-API catalog ids stop surfacing as routable chat models (#11060)
1 change: 1 addition & 0 deletions changelog.d/fixes/11085-claude-code-tool-name-casing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **fix(claude):** restore canonical tool names (`bash` → `Bash`, `croncreate` → `CronCreate`) on non-streaming OpenAI→Claude conversion and through identity-echo alias maps, so Claude Code stops rejecting tool calls with "No such tool available" ([#11085](https://github.com/diegosouzapw/OmniRoute/pull/11085)) — thanks @linhdmn
1 change: 1 addition & 0 deletions changelog.d/fixes/11095-termux-onnx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- fix(install): make the ONNX dependency chain optional so Termux/Android installs succeed again (#11095)
1 change: 1 addition & 0 deletions changelog.d/fixes/11101-reject-silent-validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **fix(providers):** Reject silent validation degradation on provider connection patch — unknown `rateLimitOverrides` keys (e.g. a typo'd `tpm`) and empty/non-numeric values now return `400` with the rejected key list instead of being silently dropped ([#11101](https://github.com/diegosouzapw/OmniRoute/pull/11101))
1 change: 1 addition & 0 deletions changelog.d/fixes/11102-combo-suggestion-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **Autopilot suggestion counter:** the combo health autopilot summary now reports `suggestionCount` (the real number of suggested actions across all issues) instead of conflating it with link counts, while keeping `actionableCount` as a deprecated alias for backward compatibility. The `run_combo_test` action now links to the dashboard with the combo id (`/dashboard/combos?test=<comboId>`) rather than the read-only API route, so operators can actually trigger a test from the UI ([#11102](https://github.com/diegosouzapw/OmniRoute/pull/11102)).
1 change: 1 addition & 0 deletions changelog.d/fixes/11103-persist-config-audit-log.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **Config audit persistence:** persist the configuration audit trail to SQLite (`config_audit_log`) instead of an in-memory buffer capped at 1000 volatile entries, and bound its growth with `cleanupConfigAudit()` driven by the `retention.configAudit` setting (default 30 days), wired into `runAutoCleanup` ([#11103](https://github.com/diegosouzapw/OmniRoute/pull/11103)).
1 change: 1 addition & 0 deletions changelog.d/fixes/11109-stream-recovery-toolcall.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- fix(sse): resume mid-stream recovery after a _completed_ tool call — `finish_reason: "tool_calls"` is now tracked per-call instead of as a general terminal marker, so truncation of trailing prose after a fully-delivered tool call is recoverable while in-flight calls stay blocked ([#11109](https://github.com/diegosouzapw/OmniRoute/pull/11109))
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **fix(providers):** `reasoning_effort` now learns the accepted values from a provider's own 400/422 response and clamps to the highest one instead of forwarding an unsupported `xhigh`/`max` (or a hardcoded `"high"` fallback) — fixes custom OpenAI-compatible connections and registered providers with no reasoning metadata ([#11116](https://github.com/diegosouzapw/OmniRoute/pull/11116)) — thanks @maxmad64bis
Loading
Loading