docs(changelog): reconcile 3-day merge burst — 16 fragments, 4 promised credits, contributors hall 32→63

- changelog.d fragments for the 20 merged PRs that landed without a bullet
  (#6072 #6308 #6323 #6538 #6556 #6586 #6611 #6647 #6675 #6698 #6757 #6759
  #6804 #6821 + ci rollup #6781/#6691/#6693 + docs rollup #6643/#6644/#6646/#6663;
  omniglyph bump #6661 folded into the #6556 bullet)
- deliver the 4 credits promised in close comments but never written:
  @alltomatos (#6819 dup of #6721), @samimozcan (#6762/#6753 subsumed by #6790),
  @chirag127 (#6756 dup of #6757), @Squawk7777 (#6565 dup of #6564 — appended to
  the existing #6564 bullet; changelog-integrity flags that edit as a removal,
  intentional: ALLOW_CHANGELOG_REMOVALS justification)
- rebuild the v3.8.47 Contributors hall from merged-PR authors + thanks credits
  + prior hall: 32 → 63 contributors
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-07-11 02:10:15 -03:00
parent c92bdd13c6
commit 6f749fef9a
19 changed files with 84 additions and 37 deletions

View File

@@ -30,7 +30,7 @@ _Living section — bullets land here as PRs merge into `release/v3.8.47` (paral
- **fix(cli):** the dashboard's Claude Code CLI card could report "Not detected"/"Not installed" even when Claude Code was genuinely installed and previously used ([#6701](https://github.com/diegosouzapw/OmniRoute/issues/6701)) — `getCliRuntimeStatus()` (`src/shared/services/cliRuntime.ts`) determined `installed` purely from binary resolution (known install paths + a `where`/`which` PATH search), with no fallback when that lookup fails for reasons unrelated to whether the CLI is actually installed (stale PATH inherited by a long-running/background process, the binary having moved, an install method not yet catalogued, etc.) — even though `~/.claude/settings.json` on disk proves the tool was installed and used before. Upstream 9router's equivalent route already has this exact fallback. A new `withSettingsFallback()` (`src/shared/services/cliInstallFallback.ts`) restores 9router parity: when the binary lookup's own reason is `"not_found"` (never for deliberate security rejections like unsafe/relative env overrides or symlink escapes) and the tool's settings file exists on disk, `installed` now reports `true`. Regression guard: `tests/unit/repro-6701-claude-detect-fallback.test.ts`.
- **fix(cli):** per-agent AgentBridge DNS toggle was broken for 8 of the 9 supported agents, and a failed MITM startup step could orphan the spawned proxy child — `addDNSEntry`/`removeDNSEntry` (`src/mitm/dns/dnsConfig.ts`) always resolved the legacy Antigravity default hosts regardless of which agent's toggle was flipped, so enabling DNS for Cursor/Codex/Claude Code/etc. silently added only `daily-cloudcode-pa.googleapis.com` while the DB recorded `dns_enabled=true` for the selected agent. Both functions now accept an optional `agentId` and resolve hosts via `ALL_TARGETS`; `POST /api/tools/agent-bridge/agents/[id]/dns` passes the route's `id` through and now returns 404 for an id that doesn't match a known target instead of silently falling back. Separately, `startMitmInternal()` (`src/mitm/manager.ts`) now wraps `generateCert()` (log + rethrow), the `provisionDnsEntries()` call, and the PID-file write in try/catch so a mid-startup failure can't orphan the already-spawned MITM child process. On Windows, `addDNSEntries`/`removeDNSEntries` also batch every missing/present entry into a single elevated PowerShell invocation instead of one UAC prompt per host line. Regression guard: `tests/unit/dns-config-generic.test.ts` (agent-specific resolution + batching), `tests/unit/agent-bridge-dns-route-validation.test.ts` (404 for unknown agent id). ([#6338](https://github.com/diegosouzapw/OmniRoute/pull/6338) — thanks @hamsa0x7)
- **fix(guardrails):** Vision Bridge's individual-model auto-reroute (route an image-bearing request straight to a vision-capable model instead of describe-then-forward) could bypass a policy-restricted API key's model allowlist/budget ([#6640](https://github.com/diegosouzapw/OmniRoute/pull/6640)) — `VisionBridgeGuardrail.preCall()` (`src/lib/guardrails/visionBridge.ts`) swaps `body.model` to the best available vision-capable model, but that swap happens in the guardrail pipeline AFTER `chat.ts` already called `enforceApiKeyPolicy()` against the ORIGINAL model, so a key scoped to a narrow `allowedModels` list could still execute against an unvetted (and possibly costlier) vision model the reroute picked. `chat.ts` now re-validates any guardrail-driven model change against the same per-key allowlist (`isModelAllowedForKey`) before honoring it, falling back to the original already-approved model when the reroute target is not allowed. The reroute path also now honors an explicit `settings.visionBridgeModel` operator override (previously ignored, unlike the combo/describe path a few lines below it, which already respects it via `getVisionBridgeConfig`). Regression guard: `tests/unit/guardrails/visionBridge.test.ts` (22 tests). (thanks @herjarsa)
- **fix(auth):** an API key restricted via `allowedModels`/`allowedCombos` could bypass that restriction entirely over the Codex Responses-over-WebSocket bridge ([#6564](https://github.com/diegosouzapw/OmniRoute/issues/6564)) — `prepare()` in `src/app/api/internal/codex-responses-ws/route.ts` authenticated the WS bridge's API key (`authenticate()`/`authorizeWebSocketHandshake()`) and honored `allowedConnections`, but never called `enforceApiKeyPolicy()`, the same model/combo policy gate the HTTP `/v1/responses` path enforces via `handleChat()` — so a key scoped to e.g. `combo/model-1.0` could still reach a direct Codex model like `gpt-5.5` through this transport, as long as an eligible Codex OAuth connection existed. The bridge's WS auth token arrives via query params (`api_key`/`token`/`access_token`), not a normal `Authorization` header, so a new `enforceCodexWsApiKeyPolicy()` builds an equivalent `Request` carrying an explicit `Authorization: Bearer <apiKey>` header and calls `enforceApiKeyPolicy()` against the CLIENT-requested model, before any Codex-specific model remapping or credential selection. Regression guard: `tests/unit/codex-ws-policy-enforcement-6564.test.ts` (a model-restricted key is rejected 403 before reaching credential selection; a combo-restricted key is rejected 403 requesting a disallowed combo; a key that DOES allow the requested model still proceeds past policy).
- **fix(auth):** an API key restricted via `allowedModels`/`allowedCombos` could bypass that restriction entirely over the Codex Responses-over-WebSocket bridge ([#6564](https://github.com/diegosouzapw/OmniRoute/issues/6564)) — `prepare()` in `src/app/api/internal/codex-responses-ws/route.ts` authenticated the WS bridge's API key (`authenticate()`/`authorizeWebSocketHandshake()`) and honored `allowedConnections`, but never called `enforceApiKeyPolicy()`, the same model/combo policy gate the HTTP `/v1/responses` path enforces via `handleChat()` — so a key scoped to e.g. `combo/model-1.0` could still reach a direct Codex model like `gpt-5.5` through this transport, as long as an eligible Codex OAuth connection existed. The bridge's WS auth token arrives via query params (`api_key`/`token`/`access_token`), not a normal `Authorization` header, so a new `enforceCodexWsApiKeyPolicy()` builds an equivalent `Request` carrying an explicit `Authorization: Bearer <apiKey>` header and calls `enforceApiKeyPolicy()` against the CLIENT-requested model, before any Codex-specific model remapping or credential selection. Regression guard: `tests/unit/codex-ws-policy-enforcement-6564.test.ts` (a model-restricted key is rejected 403 before reaching credential selection; a combo-restricted key is rejected 403 requesting a disallowed combo; a key that DOES allow the requested model still proceeds past policy). (thanks @Squawk7777 for the report and an independent fix via #6565)
- **fix(security):** loopback-gate `/api/middleware/*` so a leaked JWT over a tunnel can't install or trigger a middleware hook — middleware hooks compile + run arbitrary JS via `new vm.Script` on the request hot path (`src/lib/middleware/registry.ts`), the same RCE class as the already-gated `/api/plugins/*`; `/api/middleware/` is now in `LOCAL_ONLY_API_PREFIXES` so loopback enforcement runs unconditionally before any auth check (Hard Rules #15 + #17). Regression guard: `tests/unit/route-guard-middleware-local-only.test.ts`. ([#6541](https://github.com/diegosouzapw/OmniRoute/pull/6541)) — see PR. (thanks @developerjillur)
- **fix(startup):** AgentBridge's MITM server no longer fails to start with `ROUTER_API_KEY is required` on a normal install ([#6403](https://github.com/diegosouzapw/OmniRoute/issues/6403)) — `POST /api/tools/agent-bridge/server` resolved the spawned MITM child's router key from only an explicit `apiKey` body field (never sent by the AgentBridge UI — the schema has no such field) and the `ROUTER_API_KEY` env var (unset by default), so `startMitm()` always received `""` and the child hard-exited, even though OmniRoute already had a usable API key in its own DB. A new `resolveRouterApiKey()` now falls back to `pickApiKeyForInternalUse()` (the same DB-backed selector the combo-health-check / cloud-sync internal probes use), resolving in order: explicit key → `ROUTER_API_KEY` env → an existing DB key. Regression guard: `tests/unit/agentbridge-mitm-router-key-6403.test.ts`.
- **fix(providers):** deploying a Cloudflare relay Worker from Dashboard → System → Proxy pool → Cloudflare relay failed immediately with `Cloudflare Worker upload failed: Content-Type must be one of: application/javascript, text/javascript, multipart/form-data`, even with a valid token/account ([#6416](https://github.com/diegosouzapw/OmniRoute/issues/6416)) — the Worker-script upload built a native `FormData` and let `fetch` derive the multipart Content-Type automatically, but in production `globalThis.fetch` is patched with `node_modules/undici`'s own fetch (`open-sse/utils/proxyFetch.ts`), whose `FormData`/`Request` classes differ from the runtime's global `FormData` (same cross-realm class mismatch already fixed once for image edits in #3273); passing a native `FormData` instance through undici's patched fetch made it serialize the body as the literal string `"[object FormData]"` with `Content-Type: text/plain;charset=UTF-8`, which Cloudflare rejects outright. `buildCloudflareWorkerUploadRequest()` (`src/lib/proxyRelay/cloudflareWorkerScript.ts`) now builds the multipart body as a raw `Buffer` with an explicit boundary and `Content-Type: multipart/form-data; boundary=…` header, accepted verbatim by any fetch implementation. Regression guard: `tests/unit/cloudflare-worker-upload-content-type-6416.test.ts` + updated `tests/unit/relay-deploy-5128.test.ts`.
@@ -83,40 +83,71 @@ _Living section — bullets land here as PRs merge into `release/v3.8.47` (paral
Thanks to everyone whose work landed in v3.8.47:
| Contributor | PRs / Issues |
| -------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| [@anki1kr](https://github.com/anki1kr) | #6041, #6078 |
| [@arssnndr](https://github.com/arssnndr) | #6163 |
| [@backryun](https://github.com/backryun) | #6154, #6235, #6248, #6331 |
| [@charleszolot](https://github.com/charleszolot) | direct commit / report |
| [@chirag127](https://github.com/chirag127) | #6145, #6189, #6265, #6328, #6400, #6402, #6404, #6405, #6406, #6407, #6408, #6412, #6414, … |
| [@developerjillur](https://github.com/developerjillur) | #6451, #6452, #6541, #6542, #6543, #6545, #6553, #6554, #6558 |
| [@dilneiss](https://github.com/dilneiss) | #6499 |
| [@DKotsyuba](https://github.com/DKotsyuba) | #6193, #6292 |
| [@dtybnrj](https://github.com/dtybnrj) | #6349 |
| [@eidoog](https://github.com/eidoog) | direct commit / report |
| [@hao3039032](https://github.com/hao3039032) | #6351 |
| [@hartmark](https://github.com/hartmark) | #6216 |
| [@Iammilansoni](https://github.com/Iammilansoni) | #6200, #6209, #6245, #6366 |
| [@jmengit](https://github.com/jmengit) | #6372, #6443 |
| [@jordansilly77-stack](https://github.com/jordansilly77-stack) | #6316 |
| [@JxnLexn](https://github.com/JxnLexn) | #6361 |
| [@kanztu](https://github.com/kanztu) | #6181 |
| [@karimalsalah](https://github.com/karimalsalah) | #6291 |
| [@KooshaPari](https://github.com/KooshaPari) | #6144, #6166, #6173, #6257 |
| [@LuisAlejandroVega](https://github.com/LuisAlejandroVega) | #6177 |
| [@makcimbx](https://github.com/makcimbx) | #6303 |
| [@Moseyuh333](https://github.com/Moseyuh333) | #6186 |
| [@pizzav-xyz](https://github.com/pizzav-xyz) | #6648 |
| [@rianonehub](https://github.com/rianonehub) | #6204 |
| [@serverless83](https://github.com/serverless83) | #6212 |
| [@shabeer](https://github.com/shabeer) | direct commit / report |
| [@swingtempo](https://github.com/swingtempo) | #6312 |
| [@Theadd](https://github.com/Theadd) | #6195 |
| [@ThongAccount](https://github.com/ThongAccount) | #6649 |
| [@vinayakkulkarni](https://github.com/vinayakkulkarni) | #6324, #6332 |
| [@VXNCXNX](https://github.com/VXNCXNX) | #6213 |
| [@xz-dev](https://github.com/xz-dev) | #6322, #6336 |
| Contributor | PRs / Issues |
| --- | --- |
| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821 |
| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 |
| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829 |
| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report |
| [@anki1kr](https://github.com/anki1kr) | #6041, #6078 |
| [@arssnndr](https://github.com/arssnndr) | #6163 |
| [@artickc](https://github.com/artickc) | #6363, #6763 |
| [@backryun](https://github.com/backryun) | #6154, #6235, #6248, #6280, #6331, #6675 |
| [@charleszolot](https://github.com/charleszolot) | #6571 |
| [@chirag127](https://github.com/chirag127) | #6145, #6189, #6265, #6328, #6400, #6402, #6404, #6405, #6406, #6407, #6408, #6412, #6414, #6513, #6515, #6516, #6517, #6519, #6521, #6523, #6525, #6526, #6532, #6534, #6546, #6547, #6548, #6549, #6550, #6551, #6552, #6577, #6643, #6644, #6645, #6646, #6703, #6756, #6757, #6769, #6804 |
| [@chy1211](https://github.com/chy1211) | direct commit / report |
| [@developerjillur](https://github.com/developerjillur) | #6451, #6452, #6541, #6542, #6543, #6545, #6553, #6554, #6558 |
| [@dilneiss](https://github.com/dilneiss) | #6499 |
| [@DKotsyuba](https://github.com/DKotsyuba) | #6193, #6292 |
| [@dtybnrj](https://github.com/dtybnrj) | #6349 |
| [@eidoog](https://github.com/eidoog) | direct commit / report |
| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647 |
| [@hajilok](https://github.com/hajilok) | #6126 |
| [@hamsa0x7](https://github.com/hamsa0x7) | #6317, #6318, #6338 |
| [@hao3039032](https://github.com/hao3039032) | #6351 |
| [@hartmark](https://github.com/hartmark) | #6216 |
| [@herjarsa](https://github.com/herjarsa) | #6640 |
| [@Iammilansoni](https://github.com/Iammilansoni) | #6200, #6209, #6245, #6366 |
| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 |
| [@itiwant](https://github.com/itiwant) | direct commit / report |
| [@janeza2](https://github.com/janeza2) | #6308 |
| [@jmengit](https://github.com/jmengit) | #6372, #6443 |
| [@jordansilly77-stack](https://github.com/jordansilly77-stack) | #6316 |
| [@JxnLexn](https://github.com/JxnLexn) | #6335, #6361 |
| [@kanztu](https://github.com/kanztu) | #6181 |
| [@karimalsalah](https://github.com/karimalsalah) | #6291 |
| [@KooshaPari](https://github.com/KooshaPari) | #6144, #6166, #6173, #6257, #6611, #6632 |
| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report |
| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report |
| [@LuisAlejandroVega](https://github.com/LuisAlejandroVega) | #6177 |
| [@makcimbx](https://github.com/makcimbx) | #6303 |
| [@MikeTuev](https://github.com/MikeTuev) | #6586 |
| [@Moseyuh333](https://github.com/Moseyuh333) | #6186, #6294, #6728 |
| [@nowhats-br](https://github.com/nowhats-br) | #6700 |
| [@oyi77](https://github.com/oyi77) | #6309 |
| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791, #6792 |
| [@pizzav-xyz](https://github.com/pizzav-xyz) | #6648 |
| [@rafpigna](https://github.com/rafpigna) | #6574 |
| [@rianonehub](https://github.com/rianonehub) | #6204 |
| [@ryanngit](https://github.com/ryanngit) | direct commit / report |
| [@samimozcan](https://github.com/samimozcan) | #6753, #6762 |
| [@samir-abis](https://github.com/samir-abis) | direct commit / report |
| [@SeaXen](https://github.com/SeaXen) | #6496, #6678 |
| [@serverless83](https://github.com/serverless83) | #6212 |
| [@shabeer](https://github.com/shabeer) | direct commit / report |
| [@Squawk7777](https://github.com/Squawk7777) | #6565 |
| [@strangersp](https://github.com/strangersp) | #6587 |
| [@swingtempo](https://github.com/swingtempo) | #6312 |
| [@Theadd](https://github.com/Theadd) | #6195 |
| [@Thinkscape](https://github.com/Thinkscape) | #6635 |
| [@ThongAccount](https://github.com/ThongAccount) | #6625, #6649 |
| [@tjengbudi](https://github.com/tjengbudi) | #4009 |
| [@vinayakkulkarni](https://github.com/vinayakkulkarni) | #6324, #6332 |
| [@VXNCXNX](https://github.com/VXNCXNX) | #6213 |
| [@whale9820](https://github.com/whale9820) | direct commit / report |
| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790 |
| [@xz-dev](https://github.com/xz-dev) | #6322, #6323, #6330, #6336, #6702, #6727 |
| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 |
---

View File

@@ -0,0 +1 @@
- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky).

View File

@@ -0,0 +1 @@
- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 5970% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:<reason>` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661).

View File

@@ -0,0 +1 @@
- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari).

View File

@@ -0,0 +1 @@
- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127).

View File

@@ -0,0 +1 @@
- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2).

View File

@@ -0,0 +1 @@
- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev).

View File

@@ -0,0 +1 @@
- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky).

View File

@@ -0,0 +1 @@
- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev).

View File

@@ -0,0 +1 @@
- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub).

View File

@@ -0,0 +1 @@
- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun).

View File

@@ -0,0 +1 @@
- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698).

View File

@@ -1 +1 @@
- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts`.
- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819).

View File

@@ -0,0 +1 @@
- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756).

View File

@@ -0,0 +1 @@
- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos).

View File

@@ -1 +1 @@
- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4).
- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753).

View File

@@ -0,0 +1 @@
- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos).

View File

@@ -0,0 +1 @@
- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693).

View File

@@ -0,0 +1 @@
- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663).