github diegosouzapw/OmniRoute v3.8.12

7 hours ago

✨ New Features

  • chipotle: add Chipotle Pepper AI — a free provider implemented via the reverse-engineered Amelia protocol, with its executor error body routed through sanitizeErrorMessage() (Hard Rule #12) (#3250 — thanks @oyi77)
  • web-cookie: add tool-call translation to 8 web-cookie executors via shared webTools helpers, so cookie-backed providers can participate in tool/function calling through a single serialize/parse path (#3259 — thanks @oyi77)
  • free-tiers: per-model free-token budget catalog + a Monthly Budget dashboard card surfacing each provider's monthly free allowance (joins the honest free-token catalog/API/headline work from #3257) (#3263, #3257 — thanks @diegosouzapw)
  • dashboard: bulk activate / deactivate / retest for selected provider connections — multi-select with batch lifecycle actions on the providers page (#3271 — thanks @leninejunior)
  • models: register MiniMax-M3 (frontier coding/agentic model, 1M context, Anthropic-compatible) across 8 provider tiers — minimax, minimax-cn, opencode (free), opencode-go, opencode-zen, trae, ollama-cloud, nvidia (#3287, #3110 — thanks @wilsonicdev)

🔧 Bug Fixes

  • api/responses: combo names without a slash (e.g. paid-premium, n8n-text) are no longer force-rewritten to codex/<combo> on /v1/responsesresolveResponsesApiModel now returns the request unchanged when the model resolves to a combo (regression from the v3.8.9 Codex WS→HTTP fallback) (#3268, fixes #3227 / #3233 — thanks @wilsonicdev; supersedes the earlier closed #3242)
  • sse: strip every <omniModel> tag before forwarding to the provider, not just the first — a global-regex variant prevents stray routing tags from leaking into the upstream prompt (#3248, fixes #454 — thanks @MikeTuev)
  • grok-web: add TLS fingerprint impersonation to bypass Cloudflare anti-bot on the Grok web endpoint, with the executor's error bodies routed through sanitizeErrorMessage() (Hard Rule #12) (#3249, fixes #3180 — thanks @wilsonicdev)
  • providers: improve provider refresh/validation and the model-catalog UI — including the OpenRouter catalog and the proxy UI, plus the NVIDIA NIM /models-suffix probe path (real-VPS validated) (#3261 — thanks @strangersp)
  • embeddings: block cross-dimension failover inside embedding combos so a fallback target with a different vector dimension can no longer corrupt results (#3256 — thanks @diegosouzapw)
  • sse/web-tools: web-cookie providers (e.g. ds-web/deepseek-v4-pro) that wrap tool calls as <tool_call name="...">{json}</tool_call> are now parsed correctly — the real tool name is read from the JSON body instead of the tag attribute, and the call is no longer silently dropped when arguments is absent (#3275, fixes #3260 — thanks @diegosouzapw)
  • sse/groq: non-reasoning Groq models (llama-3.3-70b-versatile, llama-4-scout) are now flagged supportsReasoning: false, so reasoning_effort / output_config.effort / thinking are stripped before dispatch instead of being forwarded and rejected with HTTP 400 — fixes the Claude Code → Groq regression of #764 (#3277, fixes #3258 — thanks @diegosouzapw)
  • api/images: POST /v1/images/edits to a custom OpenAI-compatible provider no longer forwards an empty model. The multipart body is now built as a Buffer with an explicit boundary instead of a global FormData — the patched undici fetch serialized a native FormData as the literal string [object FormData] (text/plain), dropping every field including model (#3278, fixes #3273 — thanks @diegosouzapw)
  • db: detect SQLite driver-unavailable errors to avoid a destructive DB rename + an optional FTS5 migration guard, so a transient driver-load failure no longer triggers the backup-and-recreate path on a healthy database (split from #3073) (#3274 — thanks @zhiru)
  • quota: repair the Quota Sharing Engine — poolUsageWithDimensions() promoted onto the QuotaStore interface (kills the dynamic type-narrowing hack), single-snapshot burn rate via computeBurnRateFromWindow() (the dashboard previously always showed 0), zero-weight allocations normalized to equal distribution, Anthropic anthropic-ratelimit-* saturation signals, a quota.exceeded webhook fired on block, and quota enforcement extended to the embeddings handler (#3280 — thanks @oyi77)
  • plugins: emitHookBlocking now chains the payload between handlers — each blocking handler receives the body/metadata as mutated by previous handlers, so a later plugin can observe an earlier plugin's changes (previously every handler got the original static payload) (#3286 — thanks @oyi77)
  • api/webhooks: webhook URLs may now target a private/internal address (e.g. 192.168.x, a docker-internal host) when OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS=true — the webhook guard reuses the same explicit opt-in as private provider URLs (default OFF; protocol and embedded-credential checks stay unconditional). Cloud-metadata / link-local endpoints (169.254.169.254, metadata.google.internal, 100.100.100.200, 169.254.0.0/16) are blocked unconditionally even with the opt-in on, and the webhook test endpoint redacts the upstream response body for private targets (no SSRF→IAM-credential pivot, no content exfiltration) (#3279, #3281, fixes #3269 — thanks @diegosouzapw)
  • sse/qoder: a valid Qoder Personal Access Token is no longer wrongly reported as "expired" when the Cosy validation endpoint returns a generic Internal Server Error (HTTP 500). A Cosy 500 only marks the PAT invalid when its body carries an explicit auth signal; a generic server fault now falls back to the #1391 valid-bypass rule (#3283, fixes #3247 — thanks @wilsonicdev, who independently diagnosed the same root cause and filed #3282; refined here to keep rejecting on an explicit-auth-signal 500)

📝 Maintenance

  • ci: deploy-vps recreates the PM2 process via the omniroute bin (instead of a bare pm2 restart pinned to the removed app/server-ws.mjs path) and gates the deploy on /api/monitoring/health reporting "status":"healthy", failing the job (with recent PM2 logs) when the box never becomes healthy — supersedes #3262 (#3270 — thanks @diegosouzapw)
  • security: harden the Chipotle executor against CodeQL findings — Math.random()crypto.randomInt()/crypto.randomUUID() (imported from node:crypto) for session/server IDs, and a strict new URL().hostname check (replacing a substring match) in its test (#3285 — thanks @oyi77)
  • governance: raise the coverage gate from 40% to 60% (statements/lines/functions/branches) now that real coverage sits at ~80% — brings the threshold in line with Hard Rule #9 (thanks @diegosouzapw)
  • docs: consolidate the community links (Discord + Telegram + WhatsApp) at the top of the README and promote the Free-Token Budget section (#3289 — thanks @diegosouzapw)
  • docs: richer free-tier budget-card image (28 models + first-month strip) and softer ToS framing (caution rather than warning) (#3284 — thanks @diegosouzapw)

🙌 Contributors

Thanks to everyone whose work landed in v3.8.12:

Contributor PRs / Issues
@oyi77 #3250, #3259, #3280, #3285, #3286
@wilsonicdev #3249, #3268, #3282 / #3283 (co-author, #3247 diagnosis), #3287
@strangersp #3261
@MikeTuev #3248
@leninejunior #3271
@zhiru #3274
@diegosouzapw maintainer — #3256, #3263, #3270, #3275, #3277, #3278, #3279, #3281, #3284, #3289

What's Changed

  • fix(sse): strip all tags before forwarding to provider by @MikeTuev in #3248
  • fix(grok-web): add TLS fingerprint impersonation to bypass Cloudflare anti-bot (#3180) by @wilsonicdev in #3249
  • feat(web-cookie): add tool-call translation to 8 executors via shared webTools helpers by @oyi77 in #3259
  • Fix provider refresh, validation, OpenRouter catalog and proxy UI by @strangersp in #3261
  • feat(provider): add Chipotle Pepper AI — free provider via reverse-engineered Amelia protocol by @oyi77 in #3250
  • fix(v1/responses): skip codex rewrite for combo names (#3233, #3227) by @wilsonicdev in #3268
  • fix(embeddings): block cross-dimension failover in embedding combos by @diegosouzapw in #3256
  • fix(ci): deploy-vps recreates PM2 via bin + gates on /login 200 by @diegosouzapw in #3270
  • fix(db): detect SQLite driver-unavailable errors to avoid destructive rename by @zhiru in #3274
  • feat(dashboard): bulk activate/deactivate/retest for selected provider connections by @leninejunior in #3271
  • feat(free-tiers): per-model free-token budget + Monthly Budget dashboard card by @diegosouzapw in #3263
  • fix(sse): parse <tool_call name=...> wrapper from web-cookie providers (#3260) by @diegosouzapw in #3275
  • fix(sse): strip reasoning_effort for non-reasoning Groq models (#3258) by @diegosouzapw in #3277
  • fix(api): build /v1/images/edits multipart as Buffer, not global FormData (#3273) by @diegosouzapw in #3278
  • fix(api): allow private webhook targets behind explicit opt-in (#3269) by @diegosouzapw in #3279
  • fix(api): harden private webhook opt-in against cloud-metadata SSRF (#3269) by @diegosouzapw in #3281
  • fix(sse): don't mark a valid Qoder PAT expired on a generic Cosy 500 (#3247) by @diegosouzapw in #3283
  • docs(free-tiers): richer budget-card image + soften ToS framing to caution by @diegosouzapw in #3284
  • fix(quota): resolve poolUsage dead code, burn rate, saturation signals, webhooks, and embeddings enforcement by @oyi77 in #3280
  • fix(security): use crypto.randomInt/randomUUID in chipotle + URL parser in test by @oyi77 in #3285
  • feat(models): add MiniMax M3 across all provider tiers (#3110) by @wilsonicdev in #3287
  • docs(readme): community block (Discord+Telegram+WhatsApp) at top + promote Free-Token Budget section by @diegosouzapw in #3289
  • fix(plugins): chain payload in emitHookBlocking + capture runOnResponse stream return by @oyi77 in #3286
  • Release v3.8.12 by @diegosouzapw in #3264

New Contributors

Full Changelog: v3.8.11...v3.8.12

Don't miss a new OmniRoute release

NewReleases is sending notifications on new releases.