From 588c683e9b2ed754ad54bfd00ad542c2bd970dd6 Mon Sep 17 00:00:00 2001 From: Xiangzhe Date: Tue, 25 Aug 2026 05:30:52 -0300 Subject: [PATCH] docs(changelog): aggregate the 363 changelog.d fragments into [3.8.50] Release reconciliation (Phase 0a.1). `scripts/release/aggregate-changelog.mjs` folds each changelog.d/
/*.md fragment into its heading in the living [3.8.50] section and deletes the fragment, which is the whole point of the fragment convention: two PRs never touch the same file, so the CHANGELOG never conflicts mid-cycle and no bullet is eaten by a merge auto-resolve. Section bullets 731 -> 1041. The remaining uncovered commits (mostly merges from #11397 onward, which landed without a fragment) are reconciled separately. --- CHANGELOG.md | 423 ++++++++++++++++++ .../10039-combo-lane-awareness-wave-2.md | 2 - .../10057-docker-aware-auto-config.md | 1 - .../features/10273-dashboard-embed-csp.md | 1 - .../features/10303-healthz-event-loop-lag.md | 1 - changelog.d/features/10316-livez-endpoint.md | 1 - .../features/10389-cloudflare-playground.md | 1 - ...0542-aihorde-optional-key-image-catalog.md | 2 - .../10556-elevenlabs-native-routes.md | 1 - .../features/10581-jina-complete-provider.md | 1 - .../features/10587-ogg-speech-alias.md | 1 - .../features/10590-google-ai-studio-tts.md | 1 - .../10617-auto-disable-banned-scope.md | 1 - changelog.d/features/10662-systemd-notify.md | 1 - .../10668-newapi-gateway-protocols.md | 2 - .../features/10670-call-logs-error-type.md | 1 - .../features/10677-egress-sharing-summary.md | 1 - .../features/10697-vscode-copilot-guide.md | 1 - .../10701-dockerfile-dashboard-embed-arg.md | 1 - ...0729-cursor-api-key-and-cli-passthrough.md | 1 - .../features/10771-health-root-endpoint.md | 1 - ...0783-task-routing-configurable-patterns.md | 1 - .../features/10869-combo-patch-verb.md | 1 - changelog.d/features/10896-glm-5.3.md | 1 - .../features/10897-home-recent-requests.md | 1 - ...0909-free-provider-rankings-reliability.md | 1 - changelog.d/features/10920-egress-ip-lock.md | 8 - .../10926-rankings-usage-reliability.md | 1 - .../features/10987-logfare-free-provider.md | 1 - .../features/11023-compression-worker-pool.md | 3 - .../features/11104-operator-error-rules.md | 1 - .../11134-configurable-max-global-attempts.md | 1 - .../features/11190-usage-command-json.md | 1 - .../11192-usage-command-providers-array.md | 1 - .../11251-connection-max-wait-ms-override.md | 1 - .../11282-first-run-readiness-card.md | 1 - .../11283-traffic-inspector-purpose-header.md | 1 - .../11286-essentials-sidebar-preset.md | 1 - .../11369-video-bridge-drilldown-isolation.md | 1 - .../11383-video-bridge-focused-mode.md | 1 - .../features/6342-cliproxy-account-health.md | 1 - ...edential-health-per-connection-interval.md | 2 - .../9085-poolside-laguna-model-ids.md | 1 - changelog.d/features/9760-video-bridge.md | 1 - .../features/9830-radar-local-model-state.md | 1 - .../features/9836-radar-guided-combos.md | 1 - .../features/9912-radar-supporter-offers.md | 1 - changelog.d/features/9923-radar-intel.md | 1 - .../features/9926-radar-launch-news.md | 1 - .../command-code-reasoning-efforts.md | 1 - .../features/crofai-reasoning-efforts.md | 1 - .../features/cursor-agent-image-provider.md | 1 - .../features/disable-context-window-checks.md | 1 - .../effort-tiers-loop-learned-sets.md | 1 - .../features/kimi-coding-extra-usage.md | 1 - .../features/m365-copilot-tool-calls.md | 1 - .../features/multimodal-embeddings-alias.md | 1 - .../opencode-go-muse-spark-efforts.md | 1 - .../per-connection-upstream-timeout.md | 1 - .../features/unreleased-detached-cli-tray.md | 1 - ...leased-exclusive-managed-session-leases.md | 1 - ...7-sse-control-lines-leak-openai-clients.md | 1 - .../10028-windows-instrumentation-hook.md | 1 - .../10060-build-sqlite-native-addon-guard.md | 1 - ...-g4f-space-anonymous-tier-proof-of-work.md | 1 - .../10077-chatgpt-web-max-thinking-effort.md | 1 - ...078-agentrouter-quota-missing-dashboard.md | 2 - ...085-compatible-chat-credential-mismatch.md | 1 - ...ity-multiaccount-quota-false-exhaustion.md | 1 - .../fixes/10096-kimi-coding-apikey-save.md | 1 - .../10104-antigravity-trailing-model-turn.md | 1 - ...111-adaptive-admission-latency-collapse.md | 1 - .../10119-claude-haiku-45-capability-flags.md | 1 - .../fixes/10123-async-call-log-artifacts.md | 1 - .../10125-incremental-call-log-rotation.md | 1 - .../fixes/10127-early-sse-heartbeat.md | 1 - .../10136-combo-scoped-session-stickiness.md | 1 - ...0139-thinking-output-cap-provider-scope.md | 1 - .../fixes/10140-conol-web-import-depth.md | 3 - .../fixes/10144-claude-import-cli-user-id.md | 1 - ...responses-commentary-completed-snapshot.md | 1 - .../fixes/10158-local-proxy-subscription.md | 1 - ...0162-approximate-combo-context-advisory.md | 1 - .../fixes/10169-thinking-budget-docs-i18n.md | 1 - ...171-instrumentation-hook-boot-fatal-log.md | 1 - ...3-10268-admission-heap-conditional-shed.md | 1 - .../fixes/10202-responses-vision-bridge.md | 1 - .../10215-cursor-kv-after-text-toolcalls.md | 1 - ...10223-deepseek-responses-sse-cjk-deltas.md | 1 - ...mbo-context-overflow-before-compression.md | 1 - ...-model-delete-tombstones-synced-sibling.md | 1 - .../10229-audio-bridge-multipart-runtime.md | 1 - .../fixes/10230-deepseek-native-max-effort.md | 1 - .../10233-freeaiapikey-endpoint-moved.md | 1 - .../10234-monsterapi-deprecation-inert.md | 1 - ...xy-installer-windows-platform-detection.md | 1 - .../10247-provider-icon-data-url-save.md | 1 - .../fixes/10248-custom-model-overrides.md | 1 - .../fixes/10249-dedup-hash-collision.md | 1 - .../fixes/10251-text-tool-call-parsing.md | 1 - .../fixes/10261-provider-warning-badges.md | 1 - .../fixes/10265-command-code-provider-api.md | 1 - ...72-provider-test-statuscode-propagation.md | 1 - .../10284-reasoning-probe-truncated-200.md | 1 - .../10285-googleflow-video-wrong-path-auth.md | 1 - .../fixes/10293-windows-tailscale-branches.md | 1 - .../10311-healthcheck-lifecycle-default.md | 1 - .../fixes/10313-catalog-cache-key-hash.md | 1 - .../fixes/10314-combo-error-aggregation.md | 1 - .../fixes/10319-live-ws-heartbeat-ping.md | 1 - .../10322-process-wide-admission-budget.md | 1 - .../fixes/10329-zai-web-auth-semantics.md | 1 - .../fixes/10345-bare-combo-opencode-ids.md | 1 - .../fixes/10346-empty-pool-warn-once.md | 1 - .../fixes/10348-default-logs-redact-client.md | 1 - .../fixes/10352-github-access-token-health.md | 1 - .../fixes/10353-memory-heap-conflict-warn.md | 1 - .../fixes/10365-gitlab-duo-401-fallback.md | 1 - .../fixes/10372-debug-mode-default-false.md | 1 - ...4-claude-tool-name-casing-normalization.md | 1 - ...openai-compatible-responses-passthrough.md | 1 - .../fixes/10381-free-tier-usage-history.md | 1 - .../10393-opencode-rotate-network-throw.md | 1 - .../fixes/10397-header-budget-warn-dedupe.md | 1 - ...ng-terminated-empty-completion-failover.md | 1 - .../10415-vision-bridge-combo-reroute.md | 1 - .../10420-antigravity-geoblock-resilience.md | 2 - .../10424-antigravity-project-autocreate.md | 2 - .../fixes/10430-antigravity-usage-envelope.md | 1 - .../fixes/10465-gemini-cached-tokens.md | 1 - ...10470-antigravity-byop-account-rotation.md | 1 - ...itm-passthrough-misroutes-unknown-hosts.md | 1 - .../fixes/10482-docker-images-and-basepath.md | 1 - .../fixes/10484-hermes-obfuscate-zwj.md | 1 - .../fixes/10489-qdrant-health-badge.md | 2 - ...10508-cli-readiness-localhost-dns-delay.md | 1 - .../10517-zed-hosted-oauth-callback-port.md | 1 - .../10518-token-backed-web-session-update.md | 1 - ...-token-backed-web-session-test-dispatch.md | 1 - .../10521-audit-extra-api-keys-redaction.md | 1 - ...22-firefly-cookie-validation-alias-miss.md | 1 - .../10523-servicesupervisor-port-flake.md | 1 - .../10527-deepseek-web-context-amnesia.md | 1 - ...irect-dispatcher-response-start-timeout.md | 1 - .../fixes/10530-codex-combo-context.md | 1 - .../10536-llmlingua-2-2.0.5-drop-tfjs.md | 1 - .../fixes/10540-deepseek-v4-efforts.md | 1 - .../fixes/10544-a2a-tasks-timing-safe.md | 1 - .../10550-responses-reasoning-transport.md | 1 - .../10553-list-models-card-hardcoded-null.md | 1 - .../fixes/10557-fedora-hostname-bind.md | 1 - ...ode-session-stability-free-tier-routing.md | 1 - .../fixes/10575-mcp-github-tool-search.md | 1 - .../fixes/10577-crof-stale-seed-catalog.md | 1 - ...83-stt-nested-model-credential-fallback.md | 1 - .../fixes/10586-audio-alias-prefix-gap.md | 1 - .../fixes/10589-elevenlabs-voice-mapping.md | 1 - ...592-playground-chattab-endpoint-routing.md | 1 - .../fixes/10594-freepik-magnific-api.md | 1 - .../fixes/10597-combo-log-error-body.md | 1 - .../fixes/10601-xai-800-message-limit.md | 1 - .../10612-cli-token-machine-id-interop.md | 1 - .../10613-setup-provider-api-key-collision.md | 1 - .../10615-api-models-v1-models-id-mismatch.md | 1 - .../10686-combo-quota-token-limit-await.md | 1 - ...vision-bridge-alias-credential-mismatch.md | 1 - ...703-modality-bridge-vision-model-filter.md | 1 - ...10705-zero-input-token-sanitization-bug.md | 1 - ...10-10711-cli-tools-timeout-hermes-keyid.md | 1 - ...0713-runtime-repair-npm12-allow-scripts.md | 1 - ...provider-metrics-ghost-deleted-provider.md | 1 - .../fixes/10720-proxy-password-only-auth.md | 1 - .../10727-meta-ai-ws-timeout-diagnostics.md | 1 - .../10732-copilot-m365-invocation-refresh.md | 1 - .../10734-combo-context-generic-default.md | 1 - .../10735-search-provider-named-errors.md | 1 - .../fixes/10736-corrupt-rotate-fence.md | 1 - .../10765-rtk-unconditional-stats-cpu.md | 1 - .../fixes/10769-cache-stats-real-cache.md | 1 - ...70-console-interceptor-message-fidelity.md | 1 - .../fixes/10774-claude-code-flat-rate.md | 1 - .../fixes/10781-wal-truncate-scheduler.md | 1 - .../fixes/10782-ws-heartbeat-ping-pong.md | 1 - .../fixes/10788-ollama-cloud-effort-tiers.md | 1 - .../10792-double-transport-retry-scope.md | 1 - ...0798-respect-log-level-provider-catalog.md | 1 - ...799-provider-health-inconclusive-probes.md | 1 - .../10815-kiro-oauth-profilearn-dedup.md | 1 - .../fixes/10815-kiro-social-multi-account.md | 1 - changelog.d/fixes/10832-unprefixed-dalle3.md | 1 - .../fixes/10843-outbound-guard-mapped-ipv4.md | 1 - .../fixes/10848-image-scan-cookie-bridge.md | 1 - .../fixes/10849-search-provider-opaque-400.md | 1 - changelog.d/fixes/10850-readyz-alias.md | 1 - .../fixes/10851-openapi-spec-auth-contract.md | 1 - .../10853-i18n-disabled-mistranslation.md | 1 - .../fixes/10854-skills-marketplace-owner.md | 1 - ...-hide-auto-models-when-routing-disabled.md | 1 - .../fixes/10858-base64-file-token-estimate.md | 1 - .../fixes/10860-mcp-upstream-fetch-timeout.md | 1 - ...862-sync-models-degraded-cached-catalog.md | 1 - changelog.d/fixes/10866-combo-empty-models.md | 1 - .../fixes/10868-proxy-echo-ipv4-fallback.md | 1 - changelog.d/fixes/10870-cli-env-collision.md | 1 - ...10873-mimocode-retirement-state-cleanup.md | 1 - .../10877-quota-alias-fetcher-lookup-gap.md | 1 - ...8-unsupported-validation-probes-neutral.md | 1 - .../10882-antigravity-gemini37-flash-tiers.md | 1 - changelog.d/fixes/10887-memory-mcp-tools.md | 1 - .../fixes/10902-pplx-search-hint-optin.md | 1 - .../10903-loopback-gate-memory-success.md | 1 - .../10935-cloudflare-relay-path-guard.md | 1 - .../10936-standalone-server-cjs-esm-scope.md | 1 - .../fixes/10940-opencode-limit-output.md | 1 - .../fixes/10941-relay-private-host-guard.md | 1 - .../fixes/10945-least-used-rotation.md | 1 - .../10947-windows-updater-artifact-name.md | 1 - .../fixes/10949-mixed-reasoning-plaintext.md | 1 - .../10953-preserve-provider-effort-tiers.md | 1 - .../fixes/10954-combo-create-models.md | 1 - changelog.d/fixes/10955-cli-ref-params.md | 1 - .../10959-single-target-reasoning-fallback.md | 1 - .../fixes/10967-10966-combo-diag-recovery.md | 2 - .../fixes/10976-skip-default-searxng.md | 1 - .../fixes/10986-reasoning-only-content.md | 1 - .../10988-release-v3850-quality-gates.md | 1 - .../fixes/10988-release-v3850-unit-shards.md | 1 - .../10990-v0-vercel-web-static-catalog.md | 1 - .../fixes/10997-blackbox-deprecation.md | 1 - .../fixes/11002-dify-key-validation.md | 1 - .../fixes/11008-account-rotation-eviction.md | 1 - .../fixes/11009-terminal-status-origin.md | 1 - .../fixes/11014-codex-drop-default-on.md | 1 - changelog.d/fixes/11015-shutdown-track-sse.md | 1 - .../fixes/11016-cred-health-disable-log.md | 1 - changelog.d/fixes/11017-rate-limit-docs.md | 1 - .../11050-remove-ghost-webhook-events.md | 1 - changelog.d/fixes/11060-perplexity-filter.md | 1 - .../11085-claude-code-tool-name-casing.md | 1 - .../11089-chat-routing-synced-inventory.md | 1 - changelog.d/fixes/11095-termux-onnx.md | 1 - .../fixes/11101-reject-silent-validation.md | 1 - .../fixes/11102-combo-suggestion-count.md | 1 - .../fixes/11103-persist-config-audit-log.md | 1 - .../fixes/11109-stream-recovery-toolcall.md | 1 - ...6-reasoning-effort-capability-discovery.md | 1 - ...144-responses-parallel-tool-calls-index.md | 1 - .../fixes/11149-opencode-go-flat-rate.md | 1 - ...11154-provider-registry-node-net-bundle.md | 1 - .../11162-combo-create-requires-model.md | 1 - ...ared-registry-passthrough-model-lockout.md | 1 - ...11180-keyless-custom-provider-auto-pool.md | 1 - .../fixes/11181-lkgp-enabled-context.md | 1 - .../fixes/11271-ollama-capability-routing.md | 1 - ...4-antigravity-empty-projectid-rejection.md | 1 - .../11297-opencode-subagent-sessionid.md | 1 - .../11311-group-model-pattern-regex-escape.md | 1 - .../11319-upstream-proxy-host-spelling.md | 1 - .../fixes/11325-i18n-pt-placeholder-parity.md | 1 - .../11326-kie-market-google-imagen-ids.md | 1 - .../11328-upstream-headers-proxy-auth.md | 1 - .../11344-video-bridge-scene-aware-sampler.md | 1 - .../11347-codex-claude-empty-tool-use.md | 1 - ...11350-video-bridge-contact-sheet-labels.md | 1 - .../fixes/11362-video-bridge-result-cache.md | 1 - .../fixes/11367-catalog-eventloop-9147.md | 1 - .../fixes/11382-video-bridge-dedup-policy.md | 1 - .../fixes/11388-live-ws-handshake-port.md | 1 - .../fixes/11394-modelsdev-interval-slider.md | 1 - ...6-electron-hollow-nested-package-repair.md | 1 - ...ectron-cold-restart-native-driver-check.md | 1 - changelog.d/fixes/7764-quota-window-order.md | 1 - ...-codex-image-account-fallback-retryable.md | 1 - changelog.d/fixes/8864-uncloseai-noauth.md | 1 - .../fixes/9013-model-param-filter-save.md | 1 - ...arch-provider-local-flag-guard-mismatch.md | 1 - ...t-file-reference-compression-corruption.md | 1 - .../fixes/9147-catalog-eventloop-yield.md | 1 - .../9303-recovery-hint-all-targets-skipped.md | 1 - .../fixes/9617-gemini-uniqueitems-strip.md | 1 - .../9692-openai-to-claude-tool-images.md | 1 - .../fixes/9708-codex-same-account-retry.md | 1 - .../fixes/9763-ratelimit-mintime-floor.md | 1 - changelog.d/fixes/9821-mcp-pack-unit-stall.md | 1 - .../9935-media-playground-masked-bearer.md | 1 - ...ential-health-search-provider-exclusion.md | 1 - ...NG-electron-window-hidden-hostname-bind.md | 1 - .../api-manager-empty-combo-allowlist.md | 1 - .../fixes/assemble-standalone-cpsync-race.md | 1 - changelog.d/fixes/auto-empty-pool-log-once.md | 1 - .../basered-deadcode-opencode-config-dir.md | 1 - .../fixes/build-advisory-hosted-runner.md | 1 - .../fixes/catalog-cache-hash-apikey.md | 1 - .../catalog-openrouter-gemini-embedding-2.md | 1 - .../claude-to-gemini-consecutive-roles.md | 1 - .../fixes/cli-update-npm-win32-11335.md | 1 - .../fixes/cline-task-id-passthrough.md | 1 - .../fixes/codex-appserver-hardening.md | 1 - changelog.d/fixes/codex-max-context-window.md | 1 - ...mbo-connection-scoped-reasoning-efforts.md | 1 - .../combo-sticky-pin-clear-on-disable.md | 1 - .../fixes/command-code-effort-capabilities.md | 1 - .../compression-run-telemetry-retention-ms.md | 1 - .../compression-worker-bundler-resolve.md | 1 - changelog.d/fixes/dbstat-optional-vtab.md | 1 - .../fixes/discovery-metadata-effort-tiers.md | 1 - .../fixes/docker-healthcheck-use-healthz.md | 1 - .../fixes/embed-gemini-missing-creds-hint.md | 1 - .../fixes/forward-codex-quota-headers.md | 1 - changelog.d/fixes/glm-credit-limit-quota.md | 1 - .../fixes/lasterror-provider-error-detail.md | 1 - .../fixes/live-ws-public-url-runtime.md | 1 - .../minimax-music-generation-dispatch.md | 1 - .../fixes/models-dev-sync-env-killswitch.md | 1 - changelog.d/fixes/opencode-force-cli-ua.md | 1 - .../fixes/opencode-merge-provider-guard.md | 1 - ...model-context-window-and-default-effort.md | 1 - .../pending-cc-cache-control-ttl-default.md | 1 - ...nding-opencode-empty-rejection-rotation.md | 1 - .../fixes/pending-opencode-jsonc-config.md | 1 - .../release-v3850-basereds-tests-i18n.md | 1 - changelog.d/fixes/release-v3850-basereds.md | 3 - .../release-v3850-turbopack-build-red.md | 1 - .../secret-leak-error-surface-hardening.md | 1 - changelog.d/fixes/sqljs-atomic-persist.md | 1 - .../10297-k8s-probe-recommendations.md | 1 - .../10317-latest-tracks-highest-stable.md | 1 - .../10349-optional-work-event-loop.md | 1 - .../10350-sqlite-single-replica-ha.md | 1 - .../10351-pre-write-backup-throttle.md | 1 - .../10704-basereds-sse-comments-vi-parity.md | 1 - .../10775-remove-dead-enforce-secrets.md | 1 - .../10778-grokbuild-suppression-fix.md | 1 - .../10779-combo-invocation-docs.md | 1 - .../10780-server-init-dead-code.md | 1 - .../10859-filesize-baseline-fix.md | 1 - .../10875-combos-id-verb-coverage.md | 1 - .../10889-feature-flag-count-fix.md | 1 - .../10906-critical-db-state-assertions.md | 1 - .../10982-runtime-ram-coding-agents.md | 1 - .../maintenance/11018-database-cache-docs.md | 1 - .../maintenance/11024-n-instance-scale-out.md | 1 - .../11038-filesize-baseline-fix.md | 1 - ...3-stryker-oauth-autoimport-registration.md | 1 - ...-v3850-basereds-docs-counts-orphan-test.md | 1 - .../11247-ratchet-no-unused-vars.md | 1 - ...1342-pnpm-optional-peers-license-policy.md | 3 - .../11345-changelog-reconciliation-ledger.md | 1 - .../maintenance/11356-readme-live-metrics.md | 5 - .../11363-openapi-try-operation-coverage.md | 1 - ...1-video-bridge-fu07-structural-sampling.md | 1 - .../maintenance/7786-management-auth-guide.md | 1 - .../maintenance/embeddings-client-runbook.md | 1 - .../maintenance/env-doc-sync-adhoc-bot.md | 1 - .../kimi-health-check-jitter-determinism.md | 1 - .../regen-translate-path-golden-freebuff.md | 1 - .../release-v3850-base-reds-20260817.md | 1 - ...se-v3850-basereds-error-helper-20260819.md | 3 - ...asereds-eslint-deadcode-vitest-20260819.md | 20 - ...ease-v3850-basereds-glm-family-20260819.md | 1 - ...se-v3850-basereds-stream-utils-20260820.md | 1 - ...lease-v3850-basereds-testdrift-20260819.md | 12 - ...elease-v3850-docs-env-basereds-20260817.md | 1 - .../maintenance/vi-harimport-parity.md | 1 - 364 files changed, 423 insertions(+), 423 deletions(-) delete mode 100644 changelog.d/features/10039-combo-lane-awareness-wave-2.md delete mode 100644 changelog.d/features/10057-docker-aware-auto-config.md delete mode 100644 changelog.d/features/10273-dashboard-embed-csp.md delete mode 100644 changelog.d/features/10303-healthz-event-loop-lag.md delete mode 100644 changelog.d/features/10316-livez-endpoint.md delete mode 100644 changelog.d/features/10389-cloudflare-playground.md delete mode 100644 changelog.d/features/10542-aihorde-optional-key-image-catalog.md delete mode 100644 changelog.d/features/10556-elevenlabs-native-routes.md delete mode 100644 changelog.d/features/10581-jina-complete-provider.md delete mode 100644 changelog.d/features/10587-ogg-speech-alias.md delete mode 100644 changelog.d/features/10590-google-ai-studio-tts.md delete mode 100644 changelog.d/features/10617-auto-disable-banned-scope.md delete mode 100644 changelog.d/features/10662-systemd-notify.md delete mode 100644 changelog.d/features/10668-newapi-gateway-protocols.md delete mode 100644 changelog.d/features/10670-call-logs-error-type.md delete mode 100644 changelog.d/features/10677-egress-sharing-summary.md delete mode 100644 changelog.d/features/10697-vscode-copilot-guide.md delete mode 100644 changelog.d/features/10701-dockerfile-dashboard-embed-arg.md delete mode 100644 changelog.d/features/10729-cursor-api-key-and-cli-passthrough.md delete mode 100644 changelog.d/features/10771-health-root-endpoint.md delete mode 100644 changelog.d/features/10783-task-routing-configurable-patterns.md delete mode 100644 changelog.d/features/10869-combo-patch-verb.md delete mode 100644 changelog.d/features/10896-glm-5.3.md delete mode 100644 changelog.d/features/10897-home-recent-requests.md delete mode 100644 changelog.d/features/10909-free-provider-rankings-reliability.md delete mode 100644 changelog.d/features/10920-egress-ip-lock.md delete mode 100644 changelog.d/features/10926-rankings-usage-reliability.md delete mode 100644 changelog.d/features/10987-logfare-free-provider.md delete mode 100644 changelog.d/features/11023-compression-worker-pool.md delete mode 100644 changelog.d/features/11104-operator-error-rules.md delete mode 100644 changelog.d/features/11134-configurable-max-global-attempts.md delete mode 100644 changelog.d/features/11190-usage-command-json.md delete mode 100644 changelog.d/features/11192-usage-command-providers-array.md delete mode 100644 changelog.d/features/11251-connection-max-wait-ms-override.md delete mode 100644 changelog.d/features/11282-first-run-readiness-card.md delete mode 100644 changelog.d/features/11283-traffic-inspector-purpose-header.md delete mode 100644 changelog.d/features/11286-essentials-sidebar-preset.md delete mode 100644 changelog.d/features/11369-video-bridge-drilldown-isolation.md delete mode 100644 changelog.d/features/11383-video-bridge-focused-mode.md delete mode 100644 changelog.d/features/6342-cliproxy-account-health.md delete mode 100644 changelog.d/features/8443-credential-health-per-connection-interval.md delete mode 100644 changelog.d/features/9085-poolside-laguna-model-ids.md delete mode 100644 changelog.d/features/9760-video-bridge.md delete mode 100644 changelog.d/features/9830-radar-local-model-state.md delete mode 100644 changelog.d/features/9836-radar-guided-combos.md delete mode 100644 changelog.d/features/9912-radar-supporter-offers.md delete mode 100644 changelog.d/features/9923-radar-intel.md delete mode 100644 changelog.d/features/9926-radar-launch-news.md delete mode 100644 changelog.d/features/command-code-reasoning-efforts.md delete mode 100644 changelog.d/features/crofai-reasoning-efforts.md delete mode 100644 changelog.d/features/cursor-agent-image-provider.md delete mode 100644 changelog.d/features/disable-context-window-checks.md delete mode 100644 changelog.d/features/effort-tiers-loop-learned-sets.md delete mode 100644 changelog.d/features/kimi-coding-extra-usage.md delete mode 100644 changelog.d/features/m365-copilot-tool-calls.md delete mode 100644 changelog.d/features/multimodal-embeddings-alias.md delete mode 100644 changelog.d/features/opencode-go-muse-spark-efforts.md delete mode 100644 changelog.d/features/per-connection-upstream-timeout.md delete mode 100644 changelog.d/features/unreleased-detached-cli-tray.md delete mode 100644 changelog.d/features/unreleased-exclusive-managed-session-leases.md delete mode 100644 changelog.d/fixes/10017-sse-control-lines-leak-openai-clients.md delete mode 100644 changelog.d/fixes/10028-windows-instrumentation-hook.md delete mode 100644 changelog.d/fixes/10060-build-sqlite-native-addon-guard.md delete mode 100644 changelog.d/fixes/10071-g4f-space-anonymous-tier-proof-of-work.md delete mode 100644 changelog.d/fixes/10077-chatgpt-web-max-thinking-effort.md delete mode 100644 changelog.d/fixes/10078-agentrouter-quota-missing-dashboard.md delete mode 100644 changelog.d/fixes/10085-compatible-chat-credential-mismatch.md delete mode 100644 changelog.d/fixes/10095-antigravity-multiaccount-quota-false-exhaustion.md delete mode 100644 changelog.d/fixes/10096-kimi-coding-apikey-save.md delete mode 100644 changelog.d/fixes/10104-antigravity-trailing-model-turn.md delete mode 100644 changelog.d/fixes/10111-adaptive-admission-latency-collapse.md delete mode 100644 changelog.d/fixes/10119-claude-haiku-45-capability-flags.md delete mode 100644 changelog.d/fixes/10123-async-call-log-artifacts.md delete mode 100644 changelog.d/fixes/10125-incremental-call-log-rotation.md delete mode 100644 changelog.d/fixes/10127-early-sse-heartbeat.md delete mode 100644 changelog.d/fixes/10136-combo-scoped-session-stickiness.md delete mode 100644 changelog.d/fixes/10139-thinking-output-cap-provider-scope.md delete mode 100644 changelog.d/fixes/10140-conol-web-import-depth.md delete mode 100644 changelog.d/fixes/10144-claude-import-cli-user-id.md delete mode 100644 changelog.d/fixes/10156-responses-commentary-completed-snapshot.md delete mode 100644 changelog.d/fixes/10158-local-proxy-subscription.md delete mode 100644 changelog.d/fixes/10162-approximate-combo-context-advisory.md delete mode 100644 changelog.d/fixes/10169-thinking-budget-docs-i18n.md delete mode 100644 changelog.d/fixes/10171-instrumentation-hook-boot-fatal-log.md delete mode 100644 changelog.d/fixes/10183-10268-admission-heap-conditional-shed.md delete mode 100644 changelog.d/fixes/10202-responses-vision-bridge.md delete mode 100644 changelog.d/fixes/10215-cursor-kv-after-text-toolcalls.md delete mode 100644 changelog.d/fixes/10223-deepseek-responses-sse-cjk-deltas.md delete mode 100644 changelog.d/fixes/10225-combo-context-overflow-before-compression.md delete mode 100644 changelog.d/fixes/10228-provider-model-delete-tombstones-synced-sibling.md delete mode 100644 changelog.d/fixes/10229-audio-bridge-multipart-runtime.md delete mode 100644 changelog.d/fixes/10230-deepseek-native-max-effort.md delete mode 100644 changelog.d/fixes/10233-freeaiapikey-endpoint-moved.md delete mode 100644 changelog.d/fixes/10234-monsterapi-deprecation-inert.md delete mode 100644 changelog.d/fixes/10244-cliproxy-installer-windows-platform-detection.md delete mode 100644 changelog.d/fixes/10247-provider-icon-data-url-save.md delete mode 100644 changelog.d/fixes/10248-custom-model-overrides.md delete mode 100644 changelog.d/fixes/10249-dedup-hash-collision.md delete mode 100644 changelog.d/fixes/10251-text-tool-call-parsing.md delete mode 100644 changelog.d/fixes/10261-provider-warning-badges.md delete mode 100644 changelog.d/fixes/10265-command-code-provider-api.md delete mode 100644 changelog.d/fixes/10272-provider-test-statuscode-propagation.md delete mode 100644 changelog.d/fixes/10284-reasoning-probe-truncated-200.md delete mode 100644 changelog.d/fixes/10285-googleflow-video-wrong-path-auth.md delete mode 100644 changelog.d/fixes/10293-windows-tailscale-branches.md delete mode 100644 changelog.d/fixes/10311-healthcheck-lifecycle-default.md delete mode 100644 changelog.d/fixes/10313-catalog-cache-key-hash.md delete mode 100644 changelog.d/fixes/10314-combo-error-aggregation.md delete mode 100644 changelog.d/fixes/10319-live-ws-heartbeat-ping.md delete mode 100644 changelog.d/fixes/10322-process-wide-admission-budget.md delete mode 100644 changelog.d/fixes/10329-zai-web-auth-semantics.md delete mode 100644 changelog.d/fixes/10345-bare-combo-opencode-ids.md delete mode 100644 changelog.d/fixes/10346-empty-pool-warn-once.md delete mode 100644 changelog.d/fixes/10348-default-logs-redact-client.md delete mode 100644 changelog.d/fixes/10352-github-access-token-health.md delete mode 100644 changelog.d/fixes/10353-memory-heap-conflict-warn.md delete mode 100644 changelog.d/fixes/10365-gitlab-duo-401-fallback.md delete mode 100644 changelog.d/fixes/10372-debug-mode-default-false.md delete mode 100644 changelog.d/fixes/10374-claude-tool-name-casing-normalization.md delete mode 100644 changelog.d/fixes/10374-openai-compatible-responses-passthrough.md delete mode 100644 changelog.d/fixes/10381-free-tier-usage-history.md delete mode 100644 changelog.d/fixes/10393-opencode-rotate-network-throw.md delete mode 100644 changelog.d/fixes/10397-header-budget-warn-dedupe.md delete mode 100644 changelog.d/fixes/10404-streaming-terminated-empty-completion-failover.md delete mode 100644 changelog.d/fixes/10415-vision-bridge-combo-reroute.md delete mode 100644 changelog.d/fixes/10420-antigravity-geoblock-resilience.md delete mode 100644 changelog.d/fixes/10424-antigravity-project-autocreate.md delete mode 100644 changelog.d/fixes/10430-antigravity-usage-envelope.md delete mode 100644 changelog.d/fixes/10465-gemini-cached-tokens.md delete mode 100644 changelog.d/fixes/10470-antigravity-byop-account-rotation.md delete mode 100644 changelog.d/fixes/10479-mitm-passthrough-misroutes-unknown-hosts.md delete mode 100644 changelog.d/fixes/10482-docker-images-and-basepath.md delete mode 100644 changelog.d/fixes/10484-hermes-obfuscate-zwj.md delete mode 100644 changelog.d/fixes/10489-qdrant-health-badge.md delete mode 100644 changelog.d/fixes/10508-cli-readiness-localhost-dns-delay.md delete mode 100644 changelog.d/fixes/10517-zed-hosted-oauth-callback-port.md delete mode 100644 changelog.d/fixes/10518-token-backed-web-session-update.md delete mode 100644 changelog.d/fixes/10519-token-backed-web-session-test-dispatch.md delete mode 100644 changelog.d/fixes/10521-audit-extra-api-keys-redaction.md delete mode 100644 changelog.d/fixes/10522-firefly-cookie-validation-alias-miss.md delete mode 100644 changelog.d/fixes/10523-servicesupervisor-port-flake.md delete mode 100644 changelog.d/fixes/10527-deepseek-web-context-amnesia.md delete mode 100644 changelog.d/fixes/10528-direct-dispatcher-response-start-timeout.md delete mode 100644 changelog.d/fixes/10530-codex-combo-context.md delete mode 100644 changelog.d/fixes/10536-llmlingua-2-2.0.5-drop-tfjs.md delete mode 100644 changelog.d/fixes/10540-deepseek-v4-efforts.md delete mode 100644 changelog.d/fixes/10544-a2a-tasks-timing-safe.md delete mode 100644 changelog.d/fixes/10550-responses-reasoning-transport.md delete mode 100644 changelog.d/fixes/10553-list-models-card-hardcoded-null.md delete mode 100644 changelog.d/fixes/10557-fedora-hostname-bind.md delete mode 100644 changelog.d/fixes/10571-opencode-session-stability-free-tier-routing.md delete mode 100644 changelog.d/fixes/10575-mcp-github-tool-search.md delete mode 100644 changelog.d/fixes/10577-crof-stale-seed-catalog.md delete mode 100644 changelog.d/fixes/10583-stt-nested-model-credential-fallback.md delete mode 100644 changelog.d/fixes/10586-audio-alias-prefix-gap.md delete mode 100644 changelog.d/fixes/10589-elevenlabs-voice-mapping.md delete mode 100644 changelog.d/fixes/10592-playground-chattab-endpoint-routing.md delete mode 100644 changelog.d/fixes/10594-freepik-magnific-api.md delete mode 100644 changelog.d/fixes/10597-combo-log-error-body.md delete mode 100644 changelog.d/fixes/10601-xai-800-message-limit.md delete mode 100644 changelog.d/fixes/10612-cli-token-machine-id-interop.md delete mode 100644 changelog.d/fixes/10613-setup-provider-api-key-collision.md delete mode 100644 changelog.d/fixes/10615-api-models-v1-models-id-mismatch.md delete mode 100644 changelog.d/fixes/10686-combo-quota-token-limit-await.md delete mode 100644 changelog.d/fixes/10702-vision-bridge-alias-credential-mismatch.md delete mode 100644 changelog.d/fixes/10703-modality-bridge-vision-model-filter.md delete mode 100644 changelog.d/fixes/10705-zero-input-token-sanitization-bug.md delete mode 100644 changelog.d/fixes/10710-10711-cli-tools-timeout-hermes-keyid.md delete mode 100644 changelog.d/fixes/10713-runtime-repair-npm12-allow-scripts.md delete mode 100644 changelog.d/fixes/10714-provider-metrics-ghost-deleted-provider.md delete mode 100644 changelog.d/fixes/10720-proxy-password-only-auth.md delete mode 100644 changelog.d/fixes/10727-meta-ai-ws-timeout-diagnostics.md delete mode 100644 changelog.d/fixes/10732-copilot-m365-invocation-refresh.md delete mode 100644 changelog.d/fixes/10734-combo-context-generic-default.md delete mode 100644 changelog.d/fixes/10735-search-provider-named-errors.md delete mode 100644 changelog.d/fixes/10736-corrupt-rotate-fence.md delete mode 100644 changelog.d/fixes/10765-rtk-unconditional-stats-cpu.md delete mode 100644 changelog.d/fixes/10769-cache-stats-real-cache.md delete mode 100644 changelog.d/fixes/10770-console-interceptor-message-fidelity.md delete mode 100644 changelog.d/fixes/10774-claude-code-flat-rate.md delete mode 100644 changelog.d/fixes/10781-wal-truncate-scheduler.md delete mode 100644 changelog.d/fixes/10782-ws-heartbeat-ping-pong.md delete mode 100644 changelog.d/fixes/10788-ollama-cloud-effort-tiers.md delete mode 100644 changelog.d/fixes/10792-double-transport-retry-scope.md delete mode 100644 changelog.d/fixes/10798-respect-log-level-provider-catalog.md delete mode 100644 changelog.d/fixes/10799-provider-health-inconclusive-probes.md delete mode 100644 changelog.d/fixes/10815-kiro-oauth-profilearn-dedup.md delete mode 100644 changelog.d/fixes/10815-kiro-social-multi-account.md delete mode 100644 changelog.d/fixes/10832-unprefixed-dalle3.md delete mode 100644 changelog.d/fixes/10843-outbound-guard-mapped-ipv4.md delete mode 100644 changelog.d/fixes/10848-image-scan-cookie-bridge.md delete mode 100644 changelog.d/fixes/10849-search-provider-opaque-400.md delete mode 100644 changelog.d/fixes/10850-readyz-alias.md delete mode 100644 changelog.d/fixes/10851-openapi-spec-auth-contract.md delete mode 100644 changelog.d/fixes/10853-i18n-disabled-mistranslation.md delete mode 100644 changelog.d/fixes/10854-skills-marketplace-owner.md delete mode 100644 changelog.d/fixes/10857-hide-auto-models-when-routing-disabled.md delete mode 100644 changelog.d/fixes/10858-base64-file-token-estimate.md delete mode 100644 changelog.d/fixes/10860-mcp-upstream-fetch-timeout.md delete mode 100644 changelog.d/fixes/10862-sync-models-degraded-cached-catalog.md delete mode 100644 changelog.d/fixes/10866-combo-empty-models.md delete mode 100644 changelog.d/fixes/10868-proxy-echo-ipv4-fallback.md delete mode 100644 changelog.d/fixes/10870-cli-env-collision.md delete mode 100644 changelog.d/fixes/10873-mimocode-retirement-state-cleanup.md delete mode 100644 changelog.d/fixes/10877-quota-alias-fetcher-lookup-gap.md delete mode 100644 changelog.d/fixes/10878-unsupported-validation-probes-neutral.md delete mode 100644 changelog.d/fixes/10882-antigravity-gemini37-flash-tiers.md delete mode 100644 changelog.d/fixes/10887-memory-mcp-tools.md delete mode 100644 changelog.d/fixes/10902-pplx-search-hint-optin.md delete mode 100644 changelog.d/fixes/10903-loopback-gate-memory-success.md delete mode 100644 changelog.d/fixes/10935-cloudflare-relay-path-guard.md delete mode 100644 changelog.d/fixes/10936-standalone-server-cjs-esm-scope.md delete mode 100644 changelog.d/fixes/10940-opencode-limit-output.md delete mode 100644 changelog.d/fixes/10941-relay-private-host-guard.md delete mode 100644 changelog.d/fixes/10945-least-used-rotation.md delete mode 100644 changelog.d/fixes/10947-windows-updater-artifact-name.md delete mode 100644 changelog.d/fixes/10949-mixed-reasoning-plaintext.md delete mode 100644 changelog.d/fixes/10953-preserve-provider-effort-tiers.md delete mode 100644 changelog.d/fixes/10954-combo-create-models.md delete mode 100644 changelog.d/fixes/10955-cli-ref-params.md delete mode 100644 changelog.d/fixes/10959-single-target-reasoning-fallback.md delete mode 100644 changelog.d/fixes/10967-10966-combo-diag-recovery.md delete mode 100644 changelog.d/fixes/10976-skip-default-searxng.md delete mode 100644 changelog.d/fixes/10986-reasoning-only-content.md delete mode 100644 changelog.d/fixes/10988-release-v3850-quality-gates.md delete mode 100644 changelog.d/fixes/10988-release-v3850-unit-shards.md delete mode 100644 changelog.d/fixes/10990-v0-vercel-web-static-catalog.md delete mode 100644 changelog.d/fixes/10997-blackbox-deprecation.md delete mode 100644 changelog.d/fixes/11002-dify-key-validation.md delete mode 100644 changelog.d/fixes/11008-account-rotation-eviction.md delete mode 100644 changelog.d/fixes/11009-terminal-status-origin.md delete mode 100644 changelog.d/fixes/11014-codex-drop-default-on.md delete mode 100644 changelog.d/fixes/11015-shutdown-track-sse.md delete mode 100644 changelog.d/fixes/11016-cred-health-disable-log.md delete mode 100644 changelog.d/fixes/11017-rate-limit-docs.md delete mode 100644 changelog.d/fixes/11050-remove-ghost-webhook-events.md delete mode 100644 changelog.d/fixes/11060-perplexity-filter.md delete mode 100644 changelog.d/fixes/11085-claude-code-tool-name-casing.md delete mode 100644 changelog.d/fixes/11089-chat-routing-synced-inventory.md delete mode 100644 changelog.d/fixes/11095-termux-onnx.md delete mode 100644 changelog.d/fixes/11101-reject-silent-validation.md delete mode 100644 changelog.d/fixes/11102-combo-suggestion-count.md delete mode 100644 changelog.d/fixes/11103-persist-config-audit-log.md delete mode 100644 changelog.d/fixes/11109-stream-recovery-toolcall.md delete mode 100644 changelog.d/fixes/11116-reasoning-effort-capability-discovery.md delete mode 100644 changelog.d/fixes/11144-responses-parallel-tool-calls-index.md delete mode 100644 changelog.d/fixes/11149-opencode-go-flat-rate.md delete mode 100644 changelog.d/fixes/11154-provider-registry-node-net-bundle.md delete mode 100644 changelog.d/fixes/11162-combo-create-requires-model.md delete mode 100644 changelog.d/fixes/11165-shared-registry-passthrough-model-lockout.md delete mode 100644 changelog.d/fixes/11180-keyless-custom-provider-auto-pool.md delete mode 100644 changelog.d/fixes/11181-lkgp-enabled-context.md delete mode 100644 changelog.d/fixes/11271-ollama-capability-routing.md delete mode 100644 changelog.d/fixes/11284-antigravity-empty-projectid-rejection.md delete mode 100644 changelog.d/fixes/11297-opencode-subagent-sessionid.md delete mode 100644 changelog.d/fixes/11311-group-model-pattern-regex-escape.md delete mode 100644 changelog.d/fixes/11319-upstream-proxy-host-spelling.md delete mode 100644 changelog.d/fixes/11325-i18n-pt-placeholder-parity.md delete mode 100644 changelog.d/fixes/11326-kie-market-google-imagen-ids.md delete mode 100644 changelog.d/fixes/11328-upstream-headers-proxy-auth.md delete mode 100644 changelog.d/fixes/11344-video-bridge-scene-aware-sampler.md delete mode 100644 changelog.d/fixes/11347-codex-claude-empty-tool-use.md delete mode 100644 changelog.d/fixes/11350-video-bridge-contact-sheet-labels.md delete mode 100644 changelog.d/fixes/11362-video-bridge-result-cache.md delete mode 100644 changelog.d/fixes/11367-catalog-eventloop-9147.md delete mode 100644 changelog.d/fixes/11382-video-bridge-dedup-policy.md delete mode 100644 changelog.d/fixes/11388-live-ws-handshake-port.md delete mode 100644 changelog.d/fixes/11394-modelsdev-interval-slider.md delete mode 100644 changelog.d/fixes/7346-electron-hollow-nested-package-repair.md delete mode 100644 changelog.d/fixes/7592-electron-cold-restart-native-driver-check.md delete mode 100644 changelog.d/fixes/7764-quota-window-order.md delete mode 100644 changelog.d/fixes/8307-codex-image-account-fallback-retryable.md delete mode 100644 changelog.d/fixes/8864-uncloseai-noauth.md delete mode 100644 changelog.d/fixes/9013-model-param-filter-save.md delete mode 100644 changelog.d/fixes/9123-search-provider-local-flag-guard-mismatch.md delete mode 100644 changelog.d/fixes/9144-github-copilot-file-reference-compression-corruption.md delete mode 100644 changelog.d/fixes/9147-catalog-eventloop-yield.md delete mode 100644 changelog.d/fixes/9303-recovery-hint-all-targets-skipped.md delete mode 100644 changelog.d/fixes/9617-gemini-uniqueitems-strip.md delete mode 100644 changelog.d/fixes/9692-openai-to-claude-tool-images.md delete mode 100644 changelog.d/fixes/9708-codex-same-account-retry.md delete mode 100644 changelog.d/fixes/9763-ratelimit-mintime-floor.md delete mode 100644 changelog.d/fixes/9821-mcp-pack-unit-stall.md delete mode 100644 changelog.d/fixes/9935-media-playground-masked-bearer.md delete mode 100644 changelog.d/fixes/9970-credential-health-search-provider-exclusion.md delete mode 100644 changelog.d/fixes/PENDING-electron-window-hidden-hostname-bind.md delete mode 100644 changelog.d/fixes/api-manager-empty-combo-allowlist.md delete mode 100644 changelog.d/fixes/assemble-standalone-cpsync-race.md delete mode 100644 changelog.d/fixes/auto-empty-pool-log-once.md delete mode 100644 changelog.d/fixes/basered-deadcode-opencode-config-dir.md delete mode 100644 changelog.d/fixes/build-advisory-hosted-runner.md delete mode 100644 changelog.d/fixes/catalog-cache-hash-apikey.md delete mode 100644 changelog.d/fixes/catalog-openrouter-gemini-embedding-2.md delete mode 100644 changelog.d/fixes/claude-to-gemini-consecutive-roles.md delete mode 100644 changelog.d/fixes/cli-update-npm-win32-11335.md delete mode 100644 changelog.d/fixes/cline-task-id-passthrough.md delete mode 100644 changelog.d/fixes/codex-appserver-hardening.md delete mode 100644 changelog.d/fixes/codex-max-context-window.md delete mode 100644 changelog.d/fixes/combo-connection-scoped-reasoning-efforts.md delete mode 100644 changelog.d/fixes/combo-sticky-pin-clear-on-disable.md delete mode 100644 changelog.d/fixes/command-code-effort-capabilities.md delete mode 100644 changelog.d/fixes/compression-run-telemetry-retention-ms.md delete mode 100644 changelog.d/fixes/compression-worker-bundler-resolve.md delete mode 100644 changelog.d/fixes/dbstat-optional-vtab.md delete mode 100644 changelog.d/fixes/discovery-metadata-effort-tiers.md delete mode 100644 changelog.d/fixes/docker-healthcheck-use-healthz.md delete mode 100644 changelog.d/fixes/embed-gemini-missing-creds-hint.md delete mode 100644 changelog.d/fixes/forward-codex-quota-headers.md delete mode 100644 changelog.d/fixes/glm-credit-limit-quota.md delete mode 100644 changelog.d/fixes/lasterror-provider-error-detail.md delete mode 100644 changelog.d/fixes/live-ws-public-url-runtime.md delete mode 100644 changelog.d/fixes/minimax-music-generation-dispatch.md delete mode 100644 changelog.d/fixes/models-dev-sync-env-killswitch.md delete mode 100644 changelog.d/fixes/opencode-force-cli-ua.md delete mode 100644 changelog.d/fixes/opencode-merge-provider-guard.md delete mode 100644 changelog.d/fixes/openrouter-synced-model-context-window-and-default-effort.md delete mode 100644 changelog.d/fixes/pending-cc-cache-control-ttl-default.md delete mode 100644 changelog.d/fixes/pending-opencode-empty-rejection-rotation.md delete mode 100644 changelog.d/fixes/pending-opencode-jsonc-config.md delete mode 100644 changelog.d/fixes/release-v3850-basereds-tests-i18n.md delete mode 100644 changelog.d/fixes/release-v3850-basereds.md delete mode 100644 changelog.d/fixes/release-v3850-turbopack-build-red.md delete mode 100644 changelog.d/fixes/secret-leak-error-surface-hardening.md delete mode 100644 changelog.d/fixes/sqljs-atomic-persist.md delete mode 100644 changelog.d/maintenance/10297-k8s-probe-recommendations.md delete mode 100644 changelog.d/maintenance/10317-latest-tracks-highest-stable.md delete mode 100644 changelog.d/maintenance/10349-optional-work-event-loop.md delete mode 100644 changelog.d/maintenance/10350-sqlite-single-replica-ha.md delete mode 100644 changelog.d/maintenance/10351-pre-write-backup-throttle.md delete mode 100644 changelog.d/maintenance/10704-basereds-sse-comments-vi-parity.md delete mode 100644 changelog.d/maintenance/10775-remove-dead-enforce-secrets.md delete mode 100644 changelog.d/maintenance/10778-grokbuild-suppression-fix.md delete mode 100644 changelog.d/maintenance/10779-combo-invocation-docs.md delete mode 100644 changelog.d/maintenance/10780-server-init-dead-code.md delete mode 100644 changelog.d/maintenance/10859-filesize-baseline-fix.md delete mode 100644 changelog.d/maintenance/10875-combos-id-verb-coverage.md delete mode 100644 changelog.d/maintenance/10889-feature-flag-count-fix.md delete mode 100644 changelog.d/maintenance/10906-critical-db-state-assertions.md delete mode 100644 changelog.d/maintenance/10982-runtime-ram-coding-agents.md delete mode 100644 changelog.d/maintenance/11018-database-cache-docs.md delete mode 100644 changelog.d/maintenance/11024-n-instance-scale-out.md delete mode 100644 changelog.d/maintenance/11038-filesize-baseline-fix.md delete mode 100644 changelog.d/maintenance/11053-stryker-oauth-autoimport-registration.md delete mode 100644 changelog.d/maintenance/11160-drain-v3850-basereds-docs-counts-orphan-test.md delete mode 100644 changelog.d/maintenance/11247-ratchet-no-unused-vars.md delete mode 100644 changelog.d/maintenance/11342-pnpm-optional-peers-license-policy.md delete mode 100644 changelog.d/maintenance/11345-changelog-reconciliation-ledger.md delete mode 100644 changelog.d/maintenance/11356-readme-live-metrics.md delete mode 100644 changelog.d/maintenance/11363-openapi-try-operation-coverage.md delete mode 100644 changelog.d/maintenance/11381-video-bridge-fu07-structural-sampling.md delete mode 100644 changelog.d/maintenance/7786-management-auth-guide.md delete mode 100644 changelog.d/maintenance/embeddings-client-runbook.md delete mode 100644 changelog.d/maintenance/env-doc-sync-adhoc-bot.md delete mode 100644 changelog.d/maintenance/kimi-health-check-jitter-determinism.md delete mode 100644 changelog.d/maintenance/regen-translate-path-golden-freebuff.md delete mode 100644 changelog.d/maintenance/release-v3850-base-reds-20260817.md delete mode 100644 changelog.d/maintenance/release-v3850-basereds-error-helper-20260819.md delete mode 100644 changelog.d/maintenance/release-v3850-basereds-eslint-deadcode-vitest-20260819.md delete mode 100644 changelog.d/maintenance/release-v3850-basereds-glm-family-20260819.md delete mode 100644 changelog.d/maintenance/release-v3850-basereds-stream-utils-20260820.md delete mode 100644 changelog.d/maintenance/release-v3850-basereds-testdrift-20260819.md delete mode 100644 changelog.d/maintenance/release-v3850-docs-env-basereds-20260817.md delete mode 100644 changelog.d/maintenance/vi-harimport-parity.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d2349f8a2..b8581eef40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,79 @@ `docs/routing/STRICT_ZERO_COST.md`. --- +- feat(services): show sanitized CLIProxyAPI account health from its authenticated management API without exposing credentials, file paths, or raw account metadata (#6342) +- **feat(credential-health):** pace the credential health sweep per connection via `provider_connections.healthCheckInterval` (minutes, 0 = never), with `CREDENTIAL_HEALTH_CHECK_INTERVAL` as the global default ([#8443](https://github.com/diegosouzapw/OmniRoute/issues/8443)) +- **behavior change:** `healthCheckInterval` is a shared column — it paces both the OAuth token refresh and the credential health sweep, and `0` disables both. The connection editor defaults it to 60, so configured OAuth connections are now credential-checked at 60min instead of the previous ~10min (aligned with the probe-volume goal of #8443) +- **feat(providers):** publish Poolside's Laguna Preview catalog statically — `poolside/laguna-xs-2.1` and `poolside/laguna-s-2.1` (262144 context, 32768 max completion, tools + reasoning, text-only), so the models are routable and visible before a key is configured instead of only after live discovery. Pins the catalog form of the XS id against the `laguna-xs.2` variant carried by third-party listings. ([#9085](https://github.com/diegosouzapw/OmniRoute/issues/9085)) +- feat(modality-bridge): bridge Chat and Responses video parts through a strict trusted-loopback, quota-bounded FFmpeg broker; enforce HTTPS redirects/SSRF plus format, protocol, stream, pixel, frame, 50 MiB broker/remote, 36 MiB inline, and 120-second limits; propagate caller aborts; preserve the actual successful fallback model through cache/meta/headers; expose sampled latency and honest success telemetry; and ship the localized Video settings UI (#9760) +- **feat(radar):** Persist local model display-name/enabled overrides and hide/restore tombstones, with authenticated catalog controls and feed safety precedence ([#9830](https://github.com/diegosouzapw/OmniRoute/pull/9830)) +- **feat(radar):** add curated-family combo suggestions, a guided combo page, and the read-only Radar MCP catalog tool ([#9836](https://github.com/diegosouzapw/OmniRoute/pull/9836)) +- **feat(radar):** add a signed live offers feed and supporter offers dashboard ([#9912](https://github.com/diegosouzapw/OmniRoute/pull/9912)) +- **feat(radar):** add signed Intel insights, supporter recognition, and local Radar CLI commands ([#9923](https://github.com/diegosouzapw/OmniRoute/pull/9923)) +- **feat(radar):** add a localized public news feed and dismissible dashboard launch banner, with the Radar announcement staged inactive for a separately authorized launch ([#9926](https://github.com/diegosouzapw/OmniRoute/pull/9926)) +- **feat(admission):** add lane-aware admission probes for combo/fusion/chaos fan-out (fail-open, queueing disabled), an env-wins `OMNIROUTE_CHAT_VIRTUAL_LANES` activation flag applied at boot, and adaptive-lane visibility in the `omniroute_get_health` MCP tool (related to #9654) +- **docs(mcp):** complete the MCP server README tool reference so the `schemas/` catalog is fully covered (agent-skills, oneproxy, web, tool-search, combo/routing, pricing and DB-health tools were previously only discoverable via `omniroute_tool_search`) +- **feat(cli):** container-aware auto-config — `setup-*`, `omniroute configure`, `omniroute config set` and the CLI-tool config APIs now refuse to write into a containerised OmniRoute's ephemeral home (CLI exits `2`, API returns `422` with `containerEphemeralTarget`) and point at the host-CLI or bind-mount setup instead; `--allow-container-write` / `OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE=true` opt back in. Also fixes `CLI_CONFIG_HOME` so the Compose `host` profile's `/host-home` bind mounts are honoured instead of silently falling back to the container home. (#10057) +- feat(dashboard): opt-in `DASHBOARD_ALLOW_EMBED=vscode` relaxes CSP `frame-ancestors` to `'self' vscode-webview:` and drops `X-Frame-Options` for HTML pages only, so the dashboard renders inside the VS Code Simple Browser (OmniCopilot). Default posture unchanged — API routes stay unframable (#10273) +- **feat(resilience):** warn when `/healthz` is served under event-loop lag ≥200ms so a slow 200 is visible as sick, not healthy ([#10303](https://github.com/diegosouzapw/OmniRoute/issues/10303)) +- **feat(docker):** add `GET`/`HEAD` `/livez` as a process-alive probe, distinct from `/healthz` readiness ([#10316](https://github.com/diegosouzapw/OmniRoute/issues/10316)) +- feat(providers): add **Cloudflare AI Playground** as a No Auth provider (`cloudflare-playground`, alias `cfp`) — free anonymous chat over the reverse-engineered `cf_agent` WebSocket protocol (PartySocket transport, no account/API key/cookies) with GLM 5.2, Kimi K2.7 Code, DeepSeek V4 Pro, gpt-oss-120B, Llama 3.3 70B, Qwen2.5 Coder 32B and 14 more curated models. The executor drives a headless Chromium via Playwright (the WS upgrade is TLS-fingerprint-gated), translates the `cf_agent` frame stream into OpenAI SSE, and surfaces upstream rate limits (3021) as HTTP 429. Fixes #10389 +- **feat(providers):** AI Horde accepts an optional registered API key and advertises only live image models that currently have workers ([#10542](https://github.com/diegosouzapw/OmniRoute/pull/10542)) +- **fix(providers):** AI Horde Check validates keys via `/v2/find_user` instead of the unauthenticated OpenAI models list ([#10542](https://github.com/diegosouzapw/OmniRoute/pull/10542)) +- **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). +- **feat(providers):** complete Jina AI as one credential pool — dashboard `jina-ai` / `jina-reader` share a token, `JINA_AI_API_KEY` is a real fallback, Test probes `GET https://api.jina.ai/v1/models` (embeddings fallback hits `jina-embeddings-v5-omni-small`), embed/rerank logs keep `connection_id`, catalog adds `jina-reranker-v3.5`, Omni v5 multimodal `{text}`/`{image}`/`{content}` docs pass through intact, and OmniRoute proxies classify / segment / `jina-search` (`s.jina.ai`). Reader stays a separate `r.jina.ai` card with an explicit label. Gemini Embedding 2 (`gemini/gemini-embedding-2`, alias `google/gemini-embedding-2`) uses dashboard `gemini` keys (or `GEMINI_API_KEY` / `GOOGLE_API_KEY` only when none exist), forwards native multimodal parts, and maps N OpenAI `input` items to N `:batchEmbedContents` vectors instead of one aggregated `:embedContent`. ([#10581](https://github.com/diegosouzapw/OmniRoute/pull/10581)) +- **feat(providers):** accept `response_format=ogg` on `/v1/audio/speech` as an alias for the existing Opus/Ogg encoder ([#10587](https://github.com/diegosouzapw/OmniRoute/issues/10587)) +- Added Google AI Studio Gemini batch text-to-speech support through `POST /v1/audio/speech`. +- **feat(settings):** add `autoDisableBannedScope` so permanent-ban auto-disable can target subscription/OAuth accounts only, leaving prepaid API keys in the routing pool ([#10617](https://github.com/diegosouzapw/OmniRoute/pull/10617)) +- feat(server): emit systemd sd_notify READY/WATCHDOG/STOPPING (generated unit becomes Type=notify with WatchdogSec=180) so a frozen server process is killed and restarted by systemd instead of lingering undetected +- **feat(providers):** add the TabiToken NewAPI gateway (`tabitoken`) and teach the existing HCNSec entry (`hcnsec`) the three further protocols it actually serves. TabiToken leaves the NewAPI pricing endpoint public, so its catalog is read from the host rather than guessed: four Claude models, each reporting the Anthropic and OpenAI protocols. HCNSec shipped OpenAI-only; probing the host showed `/v1/messages`, `/v1/responses` and the Gemini `/v1beta` path all reach its token layer, so each is now declared as an alternate format — with its default format, base URL, auth scheme and regional catalog classification untouched. ([#10668](https://github.com/diegosouzapw/OmniRoute/pull/10668)) — thanks @yawar-aquil +- **feat(sse):** allow an alternate protocol to build its own upstream URL. `AlternateFormat` gained an optional `urlBuilder`, because the Gemini protocol carries the model inside the path (`{base}/{model}:generateContent`) and the existing `chatPath`/`urlSuffix` fields are constants that cannot express it. The route builder is extracted as `buildGeminiGenerateContentUrl` and shared with the native `gemini` provider so the two consumers cannot drift on the `?alt=sse` streaming suffix. ([#10668](https://github.com/diegosouzapw/OmniRoute/pull/10668)) — thanks @yawar-aquil +- **feat(call_logs):** persist the per-call error family in `call_logs.error_type` and expose a failure breakdown (`errorBreakdown`) in the usage analytics endpoint, reusing the existing production classifier ([#10670](https://github.com/diegosouzapw/OmniRoute/issues/10670)) +- **feat(proxy):** the proxy-health sweep and `GET /api/settings/proxies/egress` now report an anonymous summary of egress-IP sharing — how many rotation groups share an egress IP and the largest number of accounts behind one IP — computed from persisted `proxy_logs` over a 24h window. No IPs and no account identities by default; `PROXY_LOG_INCLUDE_IPS=true` restores raw details. ([#10677](https://github.com/diegosouzapw/OmniRoute/issues/10677)) +- **docs(guides):** OmniRoute now serves VS Code's **native Copilot Chat model picker** through the [OmniCopilot](https://github.com/diegosouzapw/OmniCopilot) extension ([Marketplace](https://marketplace.visualstudio.com/items?itemName=diegosouzapw.omnicopilot) · [Open VSX](https://open-vsx.org/extension/diegosouzapw/omnicopilot) — Cursor, Windsurf, VSCodium, Theia…) — no Copilot subscription needed since VS Code 1.122. New [`docs/guides/VSCODE-COPILOT.md`](docs/guides/VSCODE-COPILOT.md) covers setup, how the picker collapses the `dual`-prefix catalog via `GET /v1/models?prefix=alias`, and the **build-time** `DASHBOARD_ALLOW_EMBED=vscode` flag that renders the dashboard in an editor tab ([#10697](https://github.com/diegosouzapw/OmniRoute/pull/10697)) +- **feat(docker):** `DASHBOARD_ALLOW_EMBED` is now a Docker build argument — `docker build --build-arg DASHBOARD_ALLOW_EMBED=vscode` produces an image whose dashboard renders inside the VS Code Simple Browser (OmniCopilot's `dashboardOpen: "editor"`). Previously the flag was only reachable from a source build: Docker silently drops a `--build-arg` with no matching `ARG`, so the operator got the default image and no error. Builder-stage only and empty by default — the runtime stages deliberately do not carry it, and the unframable default posture is unchanged ([#10701](https://github.com/diegosouzapw/OmniRoute/pull/10701)) +- **feat(providers):** new `cursor-api` provider (card "Cursor API", alias `cua`): connect a Cursor user API key (`crsr_…`) and route `cursor-api/` through the existing Cursor agent executor (the key is exchanged for a 1h session token and cached), plus a `/api/cursor-cli/*` passthrough so the Cursor CLI itself runs through OmniRoute (`CURSOR_API_ENDPOINT=http:///api/cursor-cli`, `CURSOR_API_KEY=`) with every RPC attributed and logged. The IDE `cursor` provider is unchanged. (#10729) +- **feat(api):** `GET /api/health` now answers `{ status, timestamp }` without a key. Until now the path had no route, so the management-auth boundary answered first with a 401 — indistinguishable from a wrong key or an unknown route, which left Docker HEALTHCHECKs and Kubernetes probes unable to tell "down" from "misconfigured". Kept deliberately minimal: version, uptime and memory stay behind the authenticated `/api/monitoring/health` ([#PRNUM](https://github.com/diegosouzapw/OmniRoute/pull/10771)). +- feat(routing): make Task-Aware Smart Routing's detection patterns operator-configurable via `settings.taskRouting.patternOverrides` (`PUT /api/settings/task-routing`) — the built-in patterns are English-only, so a non-English dashboard had no recourse short of turning detection off entirely; an override now replaces the pattern list for one task type without touching the rest (#10783) +- feat(api): accept PATCH on /api/combos/[id], the verb the OpenAPI spec already documents (#10869) +- **feat(sse):** add GLM-5.3 support (`glm-5.3`, `glm-5.3-high`, `glm-5.3-low`) across the z.ai first-party providers, mapping the upstream `reasoning_effort` request parameter to the existing 5.2 tier UX ([#10896](https://github.com/diegosouzapw/OmniRoute/pull/10896)) — thanks @phuongddx +- **feat(home):** add a live **Recent Requests** panel beside the home Provider Topology (polls `GET /api/usage/call-logs?excludeTests=1` every ~3s, gated by the topology appearance toggle + page visibility). `excludeTests` is now an allowlist of real provider inference (`/v1/%` or `/api/v1/%`), applied before `LIMIT`, so connection-test/model-sync/management rows can never leak into the feed ([#10897](https://github.com/diegosouzapw/OmniRoute/pull/10897), extracted from [#8450](https://github.com/diegosouzapw/OmniRoute/pull/8450)) — thanks @nguyenha935 +- **feat(rankings):** free provider rankings now expose a `reliability` field (raw `testStatus`/`rateLimitedUntil` per connection plus a `healthy`/`degraded`/`down` state, reusing the `ProviderHealthState` vocabulary of the provider health matrix) when the configured/available filters are active — derived from already-loaded data, without touching the ranking order ([#10909](https://github.com/diegosouzapw/OmniRoute/pull/10909)) +- `feat(resilience)`: when an allowlisted provider (opencode family) answers + 429 classified `quota_exhausted` or `rate_limit_exceeded` and its free-tier + quota is bucketed by egress IP (#9611), every connection of that family + sharing the IP is cooled down together before the rotation tries them — one + guaranteed-failed upstream call per episode instead of N, on the combo path + as well. For the allowlisted family a 429 now cools the connection instead + of locking a single model. Exclusive allowlist, never terminal, best-effort + when the egress IP is unknown (#10920). +- **feat(rankings):** free provider rankings can now report what each provider actually served — `reliability.usage` (requests, successes, success rate over a window) behind the opt-in `withUsage`/`usageRange` query parameters, so a provider that answers every call with an error is no longer described as healthy ([#10926](https://github.com/diegosouzapw/OmniRoute/pull/10926)) +- **feat(providers):** add Logfare as a free OpenAI-compatible provider — dashboard card with a Free badge and request-logging disclosure (every prompt/completion is logged for research; opt out at logfare.ai/consent), live model discovery from `https://logfare.ai/v1/models` (20 models, 11 chat-capable: kimi-k3, deepseek-v4-pro, glm-5.2, gpt-5.6-luna, minimax-m3…), full chat/streaming through the existing OpenAI-compatible path, the real Logfare logo on the card, and a listing in the free-tiers guide. ([#10987](https://github.com/diegosouzapw/OmniRoute/pull/10987)) +- 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. +- **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)) +- **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)) +- **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)) +- **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)) +- **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) +- **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)) +- **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)) +- **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)) +- **feat(video bridge):** harden the optional drill-down cache substrate with exact-path broker policy, canonical principal/session/media isolation, independent retained-byte quotas, cancellation-safe commits, rejection of excess or non-canonical Base64 padding and non-JPEG/truncated media, warning-sensitive full JPEG canonicalization that strips trailing polyglot bytes, server-derived dimensions, and auditable derivation metadata; production tenant binding and multi-resolution selection remain follow-up work ([#11369](https://github.com/diegosouzapw/OmniRoute/pull/11369)) +- **feat(video):** add an opt-in focused analysis mode that safely uses a normalized, 500-code-point latest-user hint for task-aware frame captions while preserving full-mode prompts, temporal-window isolation, and cache identity without storing raw task text ([#11383](https://github.com/diegosouzapw/OmniRoute/pull/11383)). +- feat(command-code): advertise low/medium/high/xhigh/max reasoning-effort suffixes for reasoning-capable models in the catalog and Combo Builder, with request-time resolution to reasoning_effort +- feat(crof): advertise reasoning-effort tiers (none/low/medium/high/max) for live-discovered and seed models, so the catalog, Playground, and Combo Builder surface - aliases and requests resolve max upstream +- feat(sse): add Cursor plan image generation via Agent CLI (`IMAGE_PROVIDERS.cursor`, format `cursor-agent-image`), reusing the chat Cursor OAuth connection +- feat(routing): add the default-off `DISABLE_CONTEXT_WINDOW_CHECKS` feature flag to let operators bypass OmniRoute's local context-window and max-input-token check for direct single-model requests, leaving upstream limits, prompt compression, and output-token caps intact. +- **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 `-` 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) +- **feat(usage):** show Kimi Coding's fixed-order Code 5-hour/7-day quota windows plus Extra Usage status, balance, monthly spend/limit, and the official Additional Credits link on Dashboard → Quota cards. +- **feat(providers):** copilot-m365-web now supports OpenAI tool calling — a router planning turn asks the substrate model (as a tool-selection assistant emitting `CALL_TOOL: name({...})` / `NO_TOOL_NEEDED` text, which bypasses its plugin-registry refusal) and validated decisions surface as `tool_calls` with `finish_reason: "tool_calls"` in both stream and non-stream modes; also flattens the full message history (assistant `tool_calls` + compacted tool results) so multi-turn agent loops keep context, replies to SignalR `type:6` keepalives, surfaces `type:3` error frames instead of a silent empty `stop`, and suppresses `writeAtCursor` text from tool-progress frames +- **feat(api):** add `GET`/`POST` `/v1/multimodal-embeddings` as an alias of `/v1/embeddings` so Jina-compatible clients do not receive HTTP 404 `unknown_route` — thanks @RaviTharuma +- feat(opencode-go): expose Muse Spark 1.2 Contributor reasoning-effort aliases (minimal/low/medium/high/xhigh) in the Combo Builder +- **feat(providers):** restore the operator-owned upstream timeout tier per connection via `providerSpecificData.timeoutMs` (preempts the maintainer-only model/provider registry tiers and the global `FETCH_TIMEOUT_MS`), and make the combo per-target timeout ceiling follow the selected connection +- **feat(cli):** run `omniroute serve --tray` as a detached desktop process after server and tray readiness, with graphical login auto-start support. +- **feat(routing):** add client-, provider-, and model-neutral exclusive managed session connection leases with API-key-bound generation fencing, durable SQLite ownership, explicit allowlist policy, and bounded 429 capacity retry semantics. ## [3.8.50] — TBD @@ -643,6 +716,279 @@ _Living section — regenerated 2026-08-12 from all cycle commits (cycle open `e - **fix(security):** resolve open CodeQL alerts ([#10188](https://github.com/diegosouzapw/OmniRoute/pull/10188)) - **fix(dashboard):** retarget Kimi promo CTA to the API platform aff link ([#10200](https://github.com/diegosouzapw/OmniRoute/pull/10200)) - **fix(build):** repair broken production build, red lint gate and SWR crash ([#10198](https://github.com/diegosouzapw/OmniRoute/pull/10198)) +- fix(cli): repair hollow externalized package dirs in the nested `/node_modules` bundle location too, not just the top-level one, fixing macOS/Linux Electron `ERR_MODULE_NOT_FOUND` on Turbopack-externalized packages (#7346) +- **Electron packaged smoke test:** add a cold-restart mode (`ELECTRON_SMOKE_COLD_RESTART=1`, wired blocking on the Linux release leg) that relaunches the packaged app against its own persisted `DATA_DIR` and asserts a native SQLite driver was selected instead of the sql.js WASM fallback, closing the regression-test gap flagged in the stale-ABI `better-sqlite3` investigation ([#7592](https://github.com/diegosouzapw/OmniRoute/issues/7592)). +- **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)) +- **fix(images):** retry Codex image generation on a sibling ChatGPT account when the requested model isn't entitled on the current account, instead of failing the request outright ([#8307](https://github.com/diegosouzapw/OmniRoute/pull/8307)). +- fix(dashboard): treat UncloseAI as a no-auth provider so the connect form no longer forces a fake API key (#8864) +- **fix(dashboard):** model-level allowed/blocked param edits now persist when the compatibility popover is closed by clicking outside, and a failed save no longer clears the edit or reports success ([#9013](https://github.com/diegosouzapw/OmniRoute/pull/9013)) +- fix(ssrf): make `getProviderOutboundGuard()` (used for search-provider connection validation, image generation and remote image fetch) honor the local-first default `OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS` the same way the chat validation guard already does, so a LAN-hosted SearXNG/Brave search provider works with only the LOCAL flag set instead of silently requiring `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` ([#9123](https://github.com/diegosouzapw/OmniRoute/issues/9123)). +- fix(compression): preserve unfenced raw code (e.g. Copilot #file references) from Caveman's prose recapitalization/whitespace cleanup, which was corrupting keyword casing and indentation (#9144) +- fix(api): yield the event loop during catalog builds and bulk-load override/hidden-model tables (#9147) +- fix(combo): recovery hint for all_targets_skipped now points at provider quota/availability instead of 'transient, just retry' (#9303) +- fix(providers): strip uniqueItems from Gemini tool schemas (Gemini rejects it with 400 'Unknown name uniqueItems') (#9617) +- **fix(translator):** convert OpenAI `image_url` blocks nested in `role: "tool"` / `tool_result` content to Claude `image` source blocks so OpenAI-compatible clients (Kimi Code CLI `ReadMediaFile`, and any other tool that returns media) no longer 400 the next Claude-format upstream turn ([#9692](https://github.com/diegosouzapw/OmniRoute/issues/9692)) +- **fix(resilience):** retry a retryable Codex pre-output 502/503/504/507 once on the same account (2–3s jitter) before cooling the connection, and stop translating that mixed pool into an all-accounts quota `429` ([#9708](https://github.com/diegosouzapw/OmniRoute/issues/9708)) +- **fix(ratelimit):** respect operator `minTimeBetweenRequestsMs` floor when relaxing the limiter on headroom — the adaptive rate-limit learning no longer silently erases a configured minimum gap between requests when the upstream reports plenty of remaining capacity ([#9763](https://github.com/diegosouzapw/OmniRoute/issues/9763)). +- **fix(test):** remove live `npm pack` from MCP files unit test (it stalled concurrent `test:unit` via prepare→husky + monorepo pack walk); keep the static #3578 `files` allowlist + negation guards in unit and fold #3821 pack assertions into `check:pack-artifact` / `check:pack-policy` (already `--ignore-scripts`). +- fix(dashboard): media mini-playgrounds authenticate via session instead of sending the masked API key as Bearer, fixing 401s under REQUIRE_API_KEY (#9935) +- fix(sse): exclude search providers from credential-health scheduler sweep to stop burning billed API queries (#9970) +- **Passthrough streaming:** stop leaking upstream SSE control lines (`id:`/`event:`/`retry:`/`:` comments) to plain OpenAI Chat-Completions-format clients, while preserving `event:` framing for OpenAI Responses API and Claude Messages API passthrough ([#10017](https://github.com/diegosouzapw/OmniRoute/issues/10017)). +- fix(cli): stop diagnosing every Next.js instrumentation-hook failure as the Android/Termux cache bug — only the Android "Unsupported platform: android" signal now triggers the Android hint, so a win32/desktop instrumentation error surfaces its real cause instead of a useless `mkdir -p ~/.cache` (#10028) +- **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. +- **fix(providers):** the five g4f.space sub-providers (Groq, Gemini, Pollinations, Ollama, NVIDIA) no longer advertise a free tier — a keyless `POST /v1/chat/completions` now returns `402 insufficient_credits` behind a proof-of-work "cake" wall (re-verified live 2026-08-22), so `hasFree` is `false` and the notes point at `g4f.dev/members.html`. The gateway still works with a member key, so its registry wiring and `authType: "optional"` are unchanged ([#10071](https://github.com/diegosouzapw/OmniRoute/issues/10071)) — thanks @chirag127 +- **fix(chatgpt-web):** Preserve native `max` thinking effort through ChatGPT Web routing ([#10077](https://github.com/diegosouzapw/OmniRoute/pull/10077)) — thanks @zannen7 +- Fix: wire AgentRouter's existing console balance fetcher into the Dashboard Quota UI (visibility gate + provider-limits data path + background sync) so its wallet balance renders instead of falling back to "Usage API not implemented" (#10078) +- Fix: AgentRouter's dollar balance now renders as a currency-formatted "$X.XX" credits row in the Dashboard Quota UI instead of a bare percentage, and an exhausted wallet always shows exactly $0.00 (#10078) +- fix(sse): bridge generic openai-compatible/anthropic-compatible provider type ids to their concrete uuid node id in credential lookup (#10085) +- fix(domain): stop treating an unreported Antigravity quota fraction (`fractionReported:false`) as 0% remaining in `quotaCache.ts`, which was falsely marking every fresh/newly-connected account as exhausted and blocking multi-account rotation (#10095) +- fix(dashboard): remap unified Kimi Code card API-key save to the admitted `kimi-coding-apikey` connection id, fixing 400 "Invalid provider" on Save (#10096) +- fix(antigravity): strip trailing model turn for native Gemini requests too, not just Claude (#10104) +- **fix(admission):** stop the adaptive latency-gradient collapse from permanently locking out ordinary requests — individually valid requests now make solo progress when the system is idle and normal pressure, and the collapsed limit actively recovers on sustained idle windows instead of being stuck; the critical-pressure fuse still wins over solo progress (#10111) +- fix(sse): downgrade client-supplied `thinking:{type:"adaptive"}` to `enabled` and gate the `context-1m-2025-08-07` beta on model eligibility when a combo/fallback re-routes a request to a non-adaptive/non-1M model like claude-haiku-4-5 (avoids "adaptive thinking is not supported on this model" and "long context beta is not yet available" 400s, #10119) +- **fix(logging):** move call-log artifact serialization and filesystem writes to a bounded singleton worker to keep request handling responsive (#10123) +- **perf(logging):** bound each scheduled call-log rotation pass to incremental database and filesystem work (#10125) +- **fix(streaming):** start early SSE heartbeats when Responses or Messages requests opt into streaming through the request body (#10127) +- **fix(combo):** scope session-stickiness bindings to their owning Combo so identical first messages cannot carry a successful target into another priority chain and bypass its configured order (fixes #10136) +- **fix(translator):** resolve the Claude thinking output cap with the routed provider so a provider-scoped-only `max_output_tokens` override is no longer invisible to `fitThinkingToMaxTokens()`, which previously let the synthesized `max_tokens` (caller room + thinking budget) go out unbounded and 400 upstream ([#10139](https://github.com/diegosouzapw/OmniRoute/issues/10139)) +- fix(providers): correct the conol-web registry fallback-models import depth, which pointed at a + non-existent `open-sse/config/services/` and made any suite loading the provider registry fail to + resolve (#10140) +- **fix(oauth):** Claude connections created via `claude-auth/import` now send required CLI headers on the bootstrap identity call and persist a `cliUserID` device identity, fixing intermittent "Third-party apps now draw from your extra usage" 400s on otherwise valid imported subscription tokens ([#10144](https://github.com/diegosouzapw/OmniRoute/pull/10144), fixes [#10143](https://github.com/diegosouzapw/OmniRoute/issues/10143)) +- **fix(sse):** Responses-passthrough `response.completed` snapshots now drop `phase:"commentary"` items the same way live SSE frames already do, so the terminal `response.output` array no longer echoes internal commentary text that was already suppressed from the stream (#10156). +- fix(proxy-subscriptions): allow local/loopback proxy-subscription fetch URLs (local-first, cloud-metadata still blocked) (#10158) +- **fix(routing):** keep approximate Combo context estimates advisory so requests reach concrete targets instead of returning a pre-dispatch 400 ([#10162](https://github.com/diegosouzapw/OmniRoute/pull/10162)) — thanks @xz-dev +- **docs(settings):** document Thinking Budget modes (passthrough vs auto-strip); fix dashboard i18n key collision that showed Auto Combo routing copy on the thinking tab; clarify independence from compression/cache ([#10169](https://github.com/diegosouzapw/OmniRoute/pull/10169)) +- fix(cli): guarantee a non-empty `[STARTUP] Fatal:` log line for any instrumentation-hook boot throw, not just DB-driver init failures (#10171) +- fix(sse): gate structural chat admission shedding on real heap pressure instead of unconditional capacity, with a bounded headroom budget so a healthy heap can no longer bypass admission control indefinitely (#10183, #10268) +- **fix(guardrails):** Vision Bridge handles OpenAI Responses `input`/`input_image` requests before combo vision filtering ([#10202](https://github.com/diegosouzapw/OmniRoute/pull/10202)) — thanks @Zartharas +- **fix(cursor):** Stop truncating pending tool calls on non-composer models when a KV checkpoint arrives after text but before the `exec_mcp` frame — the KV short-circuit is now gated to the composer family where it was verified ([#10215](https://github.com/diegosouzapw/OmniRoute/issues/10215)). +- **fix(responses):** repair corrupted SSE deltas for non-ASCII streams by keeping a single stream-aware `TextDecoder` (`{ stream: true }`) across `transform()` calls instead of recreating it per chunk and decoding without the `stream` flag. When a multi-byte UTF-8 character (CJK/emoji) was split across two TCP chunks — common in Chinese streaming text — the per-chunk decoder truncated it to `U+FFFD`, corrupting every delta while the rebuilt `*.done` snapshot stayed internally identical ([#10223](https://github.com/diegosouzapw/OmniRoute/issues/10223)) +- **fix(combo):** defer the known-context-overflow hard rejection for compressible requests so compression runs before the final context gate, instead of a raw-body estimate 400'ing generic Responses clients targeting a large model before OmniRoute can shrink it ([#10225](https://github.com/diegosouzapw/OmniRoute/issues/10225)) +- **fix(api):** deleting a manually-added custom model no longer tombstones a provider-synced model that shares its id. `DELETE /api/provider-models` is addressed by `provider` + `model` alone, so when both a custom row and a synced row existed for one id it removed both and wrote `isDeleted:true`. `replaceSyncedAvailableModelsForConnection` then filtered that id out of every subsequent re-import, so the provider could never resync — model sync kept reporting `added: N` while the catalog stayed empty and `/v1/models` never listed the model again, even though routing to it still worked. The custom row is now removed first and its presence is treated as the operator's intent, leaving the synced sibling importable; a synced-only delete still tombstones as before (#3199, #3782 unaffected) ([#10228](https://github.com/diegosouzapw/OmniRoute/pull/10228)) — thanks @Neuron-Mr-White +- **Audio Bridge:** fix production transcription self-loop uploads so real audio reaches the configured STT provider instead of falling back to an unavailable-provider stub ([#10229](https://github.com/diegosouzapw/OmniRoute/pull/10229)). +- **fix(api):** DeepSeek V4's native `max` reasoning tier is now reachable. DeepSeek accepts `reasoning_effort` `low`/`high`/`max` and maps `medium`/`xhigh` down to `high`, while OmniRoute's canonical vocabulary collapses `max` onto `xhigh` — so `{"effort":"max"}` silently resolved to `high` and the catalog never advertised a `max` tier (or its `-max` variant). Following the existing `extendCodexGpt56EffortValues` precedent, the native tier is now preserved for `deepseek`/`ds` V4 models only; the global effort vocabulary is unchanged, routed namespaces (`openrouter/deepseek/…`, `tllm/deepseek_v4`, `oc/deepseek-v4-flash-free`) keep the canonical behavior, and an explicit client `reasoning_effort` still wins ([#10230](https://github.com/diegosouzapw/OmniRoute/pull/10230)) — thanks @Neuron-Mr-White +- **fix(providers):** FreeAIAPIKey now targets `api.freeaiapikey.com`, the host upstream names in its `410 endpoint_moved` response — every request through the provider was failing — and its catalog is resynced to the 10 models the live `/v1/models` actually serves ([#10233](https://github.com/diegosouzapw/OmniRoute/pull/10233)) +- **fix(providers):** MonsterAPI's deprecation now actually applies — the flag was written as `isDeprecated`, a key no consumer or schema reads, so the provider kept rendering as healthy in the dashboard, the onboarding wizard and the generated provider reference ([#10234](https://github.com/diegosouzapw/OmniRoute/pull/10234)) +- **fix(cliproxy):** read platform/arch at runtime via `os.platform()`/`os.arch()` in `binaryManager` so the embedded installer selects the Windows/ARM assets even when the release bundle is built on a Linux runner (fixes #10244) +- **fix(providers):** compatible/custom providers now save valid Data URL icons and show Add/Edit save failures instead of silently doing nothing ([#10247](https://github.com/diegosouzapw/OmniRoute/pull/10247)) — thanks @xz-dev +- **fix(models):** custom model metadata and compatible-provider context overrides now take precedence over discovered metadata, while deleting a synced model no longer creates a permanent tombstone so a later provider sync can restore it ([#10248](https://github.com/diegosouzapw/OmniRoute/pull/10248)) — thanks @jackjinke +- fix(open-sse): stop concurrent requests colliding on the same dedup hash for non-OpenAI target formats (#10249) +- **fix(translator):** Text-format tool calls emitted inline by some models are now converted to proper `tool_use` blocks. Certain models (DeepSeek, Qwen) return tool invocations as `{"name":"Bash","arguments":{…}}` or `TOOL_CALL Read: {"file_path":"…"}` inside the text stream instead of the structured `tool_calls` field. Both formats leaked through the Claude translators as plain text, so Claude Code rendered the raw block and stalled instead of executing the tool. `extractXmlInvokeBlocks` (previously ``-only) now scans for all three shapes in a single pass and emits `content_block_start`/`input_json_delta`/`content_block_stop` events, in both `openai-to-claude` and `gemini-to-claude` (Antigravity) paths ([#10251](https://github.com/diegosouzapw/OmniRoute/pull/10251)) +- fix(dashboard): make provider card warning indicators expose the interaction they advertise (#10261) +- fix(command-code): route chat to the documented /provider/v1/chat/completions endpoint instead of the CLI-only /alpha/generate, which Command Code gates/blocks for external callers (#10265) +- **fix(providers):** preserve validator HTTP status codes in API-key and web connection-test results so callers can distinguish authentication, rate-limit, and upstream failures ([#10272](https://github.com/diegosouzapw/OmniRoute/pull/10272)) — thanks @Zartharas +- **fix(sse):** tiny-budget reasoning probes (e.g. Claude Code's `/model` check sends `max_tokens: 1`) are answered with a valid truncated 200 instead of relaying the upstream 5xx "empty response content" — which previously also marked the connection unavailable and poisoned fallback/cooldown bookkeeping for a request that is only a probe ([#10281](https://github.com/diegosouzapw/OmniRoute/issues/10281)) — thanks @harkaranbrar7 +- fix(video): stop advertising the googleflow (Veo) video provider as working and fail fast with a clear diagnostic — its submit/poll endpoints 404 and no server-side OAuth transport can satisfy the working endpoint (#10285) +- **fix(build):** stop Turbopack from dead-code-eliminating the Windows Tailscale branches of `src/lib/tailscaleTunnel.ts` in the published build (#10293). The release `dist` is bundled on a Linux runner, and the bundler constant-folds `process.platform`, pruning every non-Linux branch — the Windows installers shipped with no `where` lookup, an always-injected `--socket`, and a lost `net start Tailscale`/windows-default-binary path. The module now reads the platform at runtime via `os.platform()` (a function call a bundler cannot fold), so the Windows branches survive on any build machine; a vitest regression test mocking `os.platform()` → `win32` guards the anti-fold invariant (RED before, GREEN after). +- **fix(ops):** Docker HEALTHCHECK defaults to the lightweight `/healthz` lifecycle probe instead of the heavy `/api/monitoring/health` path, with an `OMNIROUTE_HEALTHCHECK_PATH` opt-in override ([#10311](https://github.com/diegosouzapw/OmniRoute/pull/10311)) +- fix(api): hash the API key before using it as the model-catalog cache Map key (no raw credentials in process heap) (#10313) +- fix(resilience): keep combo quality and auth failure reasons separate and redact connection labels in terminal errors (#10314) +- fix(dashboard): send periodic WS heartbeat pings so live dashboard connections stop dropping every ~35s (#10319) +- **fix(chat-body-admission):** restore a single process-wide admission budget — heavyweight leases and queued bytes are now bounded once for the whole process instead of per session, so one session can no longer mint extra capacity or starve others; per-session fairness is preserved via round-robin dispatch ([#10110](https://github.com/diegosouzapw/OmniRoute/issues/10110)) +- **fix(providers):** validate Z.ai web Local Storage sessions against the authenticated user-settings endpoint and preserve exact upstream status codes ([#10329](https://github.com/diegosouzapw/OmniRoute/pull/10329)) — thanks @Zartharas +- **fix(opencode-plugin):** publish bare combo model ids without the plugin provider prefix so OpenCode can select them ([#10345](https://github.com/diegosouzapw/OmniRoute/issues/10345)) +- **fix(backend):** log `auto/ matched no connected models` once per process per label instead of every minute ([#10346](https://github.com/diegosouzapw/OmniRoute/issues/10346)) +- fix(backend): redact client IPs and account prefixes from default proxy logs (#10348) +- **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 +- **fix(docker):** warn at boot when `OMNIROUTE_MEMORY_MB` disagrees with `NODE_OPTIONS --max-old-space-size`, and document that the standalone/Docker launcher appends `OMNIROUTE_MEMORY_MB` last ([#10353](https://github.com/diegosouzapw/OmniRoute/issues/10353)) +- fix(providers): GitLab Duo falls back to the public Code Suggestions endpoint when direct_access returns 401 (#10365) +- **fix(db):** `getSettings()` defaults `debugMode` to `false` — fresh installs no longer run in debug mode (persisted `debugMode: true` is preserved) ([#10372](https://github.com/diegosouzapw/OmniRoute/pull/10372) — thanks @lamchun1110) +- **fix(translator):** Consolidate tool-name casing normalization into a single `restoreClaudeToolName` helper reused across every response path (`openai-to-claude`, `gemini-to-claude`, `stream` passthrough, xAI and Antigravity handlers), replacing six hand-copied 7-entry casing maps. The shared helper resolves via the request-side `toolNameMap` first (preserving declared PascalCase and MCP/alias names), then the complete `TOOL_RENAME_MAP` (which already covers `glob`/`grep`/`task`/`todowrite`/`skill`/`askuserquestion`/etc.), then the `#7926` TitleCase→lowercase fallback for map-less clients. This closes the coverage gap that left `TodoWrite` and other tools failing with `Error: No such tool available: todowrite`, fixes a `ReferenceError` in `remapToolNamesInResponse`, and preserves the Gemini thought-signature persistence (`#8979`) and OpenAI→Claude `toolNameMap` restoration that must not regress ([#10374](https://github.com/diegosouzapw/OmniRoute/issues/10374)) +- **fix(responses):** preserve native tool definitions for custom OpenAI-compatible providers when using the Responses API (`/v1/responses`). When `apiType` is set to `"responses"` (or `_omnirouteForceResponsesUpstream` is enabled), OmniRoute passes native tool shapes (`custom` with lark grammars, `namespace`, `local_shell`) directly upstream without running a lossy Responses→Chat→Responses conversion ([#10374](https://github.com/diegosouzapw/OmniRoute/issues/10374)) +- fix(dashboard): Free Tier 'used this month' now includes live usage_history rows, not just the rolled-up daily summary (#10381) +- **fix(executors):** OpencodeExecutor and MimocodeExecutor now rotate to the next account on network exceptions (timeout, connection refused/reset) when the failed account has a dedicated proxy, not only on 429 — a throw on one account no longer fails the whole request when other accounts remain. Accounts sharing the default egress (no proxy) fail fast instead of retrying the same outage against every account. The shared rotation mechanics (`pickAccount`/`markCooldown`/`markSuccess`) are now extracted into `accountRotation.ts`, fixing an identical unconditional-cooldown gap that pre-dated this PR in MimocodeExecutor ([#10393](https://github.com/diegosouzapw/OmniRoute/pull/10393)) +- **fix(sse):** the header-budget drop warning fires once per unique dropped-header set instead of on every SSE response (warn-storm fix) ([#10397](https://github.com/diegosouzapw/OmniRoute/pull/10397) — thanks @lamchun1110) +- fix(sse): fail over combo streaming responses that reach `finish_reason` with zero content, reasoning, or tool_calls instead of forwarding a terminated-but-empty completion (#10404) +- **fix(guardrails):** Vision Bridge now reroutes whole requests for named combos whose targets have zero vision-capable models (previously such image requests died with `capability_mismatch` when the describe path could not run), and when the fallback describe path also fails for every image the request degrades to explicit `(unavailable)` stub text instead of preserving images the combo cannot consume ([#10415](https://github.com/diegosouzapw/OmniRoute/pull/10415)) — thanks @rqzbeh +- **fix(antigravity):** geo-blocked egress (Google "User location is not supported") is now classified (scoped to the Google AI surfaces that emit it: Cloud Code/Gemini Code Assist, Gemini API, Vertex), cached as a 24h per-account exclusion so routing continues with other accounts, and surfaced with an actionable message; the dashboard connection test now probes the real `streamGenerateContent` model surface instead of the non-geo-restricted OAuth userinfo endpoint ([#10420](https://github.com/diegosouzapw/OmniRoute/pull/10420)) — thanks @rqzbeh +- **fix(antigravity):** strip competing-agent identity sentences from system prompts (e.g. "You are a Claude agent, built on Anthropic's Claude Agent SDK.") that Antigravity flags and answers with 429 RESOURCE_EXHAUSTED (port of decolua/9router b566b20) ([#10420](https://github.com/diegosouzapw/OmniRoute/pull/10420)) — thanks @rqzbeh +- **fix(antigravity):** accounts with an empty Cloud Code `projectId` now heal themselves — failed auto-onboarding (`onboardUser`) attempts are retried after a short backoff instead of being memoized forever, so the missing Google project is created without user action on a later request or token refresh ([#10424](https://github.com/diegosouzapw/OmniRoute/pull/10424)) — thanks @rqzbeh +- **fix(antigravity):** Google deprecated automatic project creation for standard-tier (personal) accounts — when `onboardUser` completes without a project id the account now fails fast with a clear `403 GCP_PROJECT_REQUIRED` message (no more generic 422 or delayed 429 RESOURCE_EXHAUSTED), and a manual GCP Project ID override is available in the connection editor so operators can enter their own project id ([#10424](https://github.com/diegosouzapw/OmniRoute/pull/10424)) — thanks @rqzbeh +- **fix(usage):** read Gemini `usageMetadata` out of the antigravity `{ response: {...} }` envelope so non-streaming requests log real token usage instead of `IN 0 | OUT 0` (port of decolua/9router#59d858b) ([#10430](https://github.com/diegosouzapw/OmniRoute/pull/10430)) — thanks @rqzbeh +- **fix(usage):** surface Gemini `cachedContentTokenCount` into `cached_tokens` for non-streaming requests so cache-hit accounting matches the OpenAI/Claude/Responses branches and the streaming path (follow-up to the #10430 envelope fix) ([#10465](https://github.com/diegosouzapw/OmniRoute/pull/10465)) — thanks @rqzbeh +- **fix(antigravity):** automatically rotate to a sibling account when one is BYOP (GCP Project ID required, `gcp_project_required` 422) — the account is excluded from selection for 24h and the request succeeds via another account instead of failing fast; the actionable 422 is surfaced only when no sibling exists (follow-up to the #10424 BYOP fast-fail) ([#10470](https://github.com/diegosouzapw/OmniRoute/pull/10470)) — thanks @rqzbeh +- fix(mitm): forward passthrough traffic to the actual requested Host instead of misrouting every non-TARGET_HOSTS request to the hardcoded Antigravity sandbox host (#10479) +- **fix(docker):** point the bifrost sidecar at the real `ghcr.io/maximhq/bifrost:v1.6.11` tag and the cliproxyapi sidecar at the official `docker.io/eceasy/cli-proxy-api:v6.9.7` image (the previously pinned tags never existed), and complete the runtime `OMNIROUTE_BASE_PATH` subpath patch for Next 16 standalone (assetPrefix + client env + baked asset URLs) so prebuilt images respect the webpath env var ([#10482](https://github.com/diegosouzapw/OmniRoute/pull/10482)) +- fix(sse): stop ZWJ-obfuscating the substring "hermes" in user messages and hostnames (#10484) +- **fix(memory):** auto-check Qdrant health on mount and stop the false-red status badge on `/dashboard/memory?tab=engine` — the badge treated "not yet checked" (`health === null`) as a failure, so a healthy Qdrant showed red after every page refresh until "Test connection" was clicked; settings changes now also invalidate the stale result and re-check after the save persists, so a health check racing the settings PUT can no longer keep the badge red until a manual re-test ([#10489](https://github.com/diegosouzapw/OmniRoute/pull/10489)) +- **test(compression):** align source-contract tests with the merged `release/v3.8.50` base (`aa912c42a`) — accept the multi-line `providerTransport` shape in `omniglyph-chatcore-plumbing` and give the pipeline-circuit-breaker fixture a `metadata.executionStages` (both structural changes landed in the base merge) ([#10489](https://github.com/diegosouzapw/OmniRoute/pull/10489)) +- fix(cli): use 127.0.0.1 for the readiness health-check poll instead of localhost, avoiding Windows DNS-resolution delays that made a healthy server report as never-ready (#10508) +- **fix(providers):** zed-hosted OAuth now redirects the browser back to the dashboard's own loopback port (auto-completing the login), and the manual paste path accepts Zed's user_id/access_token callback URL instead of erroring with "No authorization code found" ([#10517](https://github.com/diegosouzapw/OmniRoute/pull/10517)) - thanks @phatchau036 +- **fix(providers):** allow token-backed web sessions stored with `authType: "cookie"` to refresh their token through the provider update API ([#10518](https://github.com/diegosouzapw/OmniRoute/pull/10518)) — thanks @Zartharas +- **fix(providers):** test token-backed web sessions through their provider validator instead of the OAuth path ([#10519](https://github.com/diegosouzapw/OmniRoute/pull/10519)) — thanks @Zartharas +- **fix(compliance):** redact additional provider API keys from audit-log payloads ([#10521](https://github.com/diegosouzapw/OmniRoute/pull/10521)) — thanks @Zartharas +- fix(providers): register a real Firefly auth probe under both the `firefly` alias and the `adobe-firefly` canonical id, and normalize the provider id before the generic web-cookie fallback, so a Firefly connection stops always reporting "Provider validation not supported" (#10522) +- fix(services): isolate probeBeforeSpawn adoption tests on distinct ports to stop the order-dependent flake (#10523) +- fix(sse): auto-replay a bounded multi-turn trajectory in the DeepSeek Web prompt builder for clients that never send `tools[]`, so agentic clients like Cline stop losing the original task after a couple of turns (#10527) +- **fix(network):** direct (no-proxy) egress now bounds each attempt's response-start window (default 30s, `OMNIROUTE_DIRECT_HEADERS_TIMEOUT_MS`) and retries once on a fresh no-keep-alive socket, so a silently-dropped pooled keep-alive connection can no longer stall direct providers (opencode-go, command-code) until a service restart ([#10214](https://github.com/diegosouzapw/OmniRoute/issues/10214)) +- **fix(models):** align Codex GPT-5.6 context limits with the Codex catalog and honor model context overrides when advertising combos ([#10530](https://github.com/diegosouzapw/OmniRoute/issues/10530)) +- **fix(deps):** upgrade `@atjsh/llmlingua-2` from 2.0.3 to 2.0.5 and remove `@tensorflow/tfjs` from the LLMLingua SLM stack — 2.0.5 adds official Transformers.js v4 support (peers `@huggingface/transformers` at `^3.5.2 || ^4.0.0`) and 2.0.4+ no longer requires TensorFlow.js, restoring compatibility with OmniRoute's Transformers.js v4 while dropping the largest single contributor to the optional runtime footprint ([#10536](https://github.com/diegosouzapw/OmniRoute/issues/10536)) +- **fix(deepseek):** Advertise `none`, `low`, `high`, and `max` for V4 Pro and Flash, derive OpenCode Go effort aliases from base-model metadata, and route those models through native Responses ([#10540](https://github.com/diegosouzapw/OmniRoute/pull/10540)) — thanks @jackjinke +- **fix(a2a):** use a constant-time bearer compare in `/api/a2a/tasks` via `crypto.timingSafeEqual`, matching the `tokensMatch` helper already used in `src/app/a2a/route.ts` and removing the last non-constant secret comparison in the repo ([#10544](https://github.com/diegosouzapw/OmniRoute/pull/10544)) +- Preserve portable plaintext reasoning by default across streaming and non-streaming Chat Completions and Responses routes while keeping provider-bound opaque state target-compatible. Direct requests drop incompatible continuation reasoning by default; combos can explicitly skip incompatible targets without mutating the request. Known providers no longer show redundant encrypted-reasoning controls. (#10550, #10959) +- fix(dashboard): show the real model count on the "List Models" endpoint card instead of a permanent "—" (#10553) +- **fix(cli):** ignore the operating system `HOSTNAME` when choosing the server bind address on Linux and macOS, preventing startup failures when the shell hostname differs from `os.hostname()`; use `OMNIROUTE_SERVER_HOST` for explicit non-Windows configuration while preserving the legacy `HOSTNAME` fallback on Windows ([#10557](https://github.com/diegosouzapw/OmniRoute/pull/10557), closes [#10492](https://github.com/diegosouzapw/OmniRoute/issues/10492)) — thanks @redzrush101 +- **fix(providers):** OpenCode `x-opencode-session` now derives a stable, conversation-scoped fingerprint via `generateSessionId()` instead of a fresh random UUID per request, so upstream prompt caching can hit across requests in the same conversation; bare `big-pickle`/`*-free` model ids now keep routing to an active opencode-family connection even when its synced catalog is temporarily stale; and bare requests to no-auth catalog providers (e.g. `opencode`) now echo the listing-valid `/` form in `response.model` so clients validating against `/v1/models` don't warn ([#10571](https://github.com/diegosouzapw/OmniRoute/pull/10571)) +- **fix(mcp):** make GitHub skill tools discoverable through `omniroute_tool_search` +- fix(providers): remove 10 retired model ids from the crof seed catalog so /v1/models stops advertising models crof.ai no longer serves (#10577) +- **fix(audio):** when a prefix-matched STT provider has no credentials, retry gateways that list the same nested model id (e.g. `deepgram/nova-3` → `openrouter/deepgram/nova-3`) and mention those ids in the 400; stop documenting bare `deepgram/nova-3` as the default example ([#10583](https://github.com/diegosouzapw/OmniRoute/issues/10583)) +- fix(sse): resolve the short provider-alias prefix (e.g. `el/`) advertised by GET /v1/models for audio speech, transcription and translation model ids (#10586) +- fix(sse): map OpenAI-compat voice names to real ElevenLabs voice_ids in direct TTS (#10589) +- fix(dashboard): route the Playground's ChatTab "Send" through the endpoint actually selected in StudioConfigPane (`search`, `web.fetch`, etc.) instead of always POSTing to `/api/v1/chat/completions`, fixing the false "No active credentials for provider" 404 when testing search-only providers (#10592) +- **fix(providers):** Magnific Mystic is now the canonical provider (`/dashboard/providers/magnific`, `magnific/`). It uses the Magnific API (`api.magnific.com` + `x-magnific-api-key`), dashboard Test Connection validates keys without starting a paid generation, and the old `freepik` slug remains a legacy alias ([#10594](https://github.com/diegosouzapw/OmniRoute/pull/10594)) +- **fix(sse):** Include the redacted upstream error body in the per-target COMBO failure log (`Model X failed, trying next`) so operators can triage a 400/500 without reproducing the request ([#10597](https://github.com/diegosouzapw/OmniRoute/issues/10597)) +- **fix(xai):** trim Chat Completions `messages` and Responses `input` to xAI's 800-item history cap before dispatch, so long tool loops no longer die on `413 Chat history exceeds the 800-message limit` ([#10601](https://github.com/diegosouzapw/OmniRoute/pull/10601)) +- **fix(cli):** derive the machine-id token correctly under plain Node — `await import("node-machine-id")` puts the CJS exports on `.default`, so the destructured `machineIdSync` was `undefined` and the catch blanked the token, sending every management request unauthenticated; `OMNIROUTE_CLI_SALT` rotation is now honored too ([#10612](https://github.com/diegosouzapw/OmniRoute/pull/10612)) +- **fix(cli):** `omniroute setup --add-provider --api-key ` no longer aborts with "Provider API key is required" — Commander bound the value to the program-level `--api-key` (the OmniRoute server key), leaving the subcommand's own option undefined; `OMNIROUTE_API_KEY` now works as the error message advertised ([#10613](https://github.com/diegosouzapw/OmniRoute/pull/10613)) +- fix(dashboard): make /api/models agree with /v1/models on synced-catalog coverage instead of reporting stale models as available (#10615) +- **Combo routing:** await each connection's token limit before reserving quota. The old lookup treated the `Promise` as a connection and dropped `rateLimitOverrides.tpm` ([#10686](https://github.com/diegosouzapw/OmniRoute/pull/10686)). +- fix(guardrails): resolve the public provider alias before querying credentials in the Vision Bridge router, so command-code/opencode (and any alias!=id provider) are no longer reported as "unusable" despite active connections (#10702) +- fix(dashboard): filter the Modality Bridge Vision model picker to vision-capable models, matching the sibling Video/Audio tabs (#10703) +- fix(usage): repair provider-reported input_tokens: 0 on non-trivial requests instead of passing it through unrepaired (#10705) +- fix(cli): distinguish a CLI-probe timeout from a genuinely absent binary in locateCommand, and resolve the Hermes Agent Apply flow's `keyId` server-side instead of writing the `YOUR_OMNIROUTE_API_KEY_HERE` placeholder (#10710, #10711) +- fix(cli): pass --allow-scripts for the runtime's own npm-installed dependencies, so npm 12+'s default install-scripts block no longer silently skips better-sqlite3's native build (#10713) +- fix(db): filter `getProviderMetrics()` to providers with a live `provider_connections` row so a deleted provider stops permanently ghost-haunting the Home "Provider Topology" widget (#10714) +- fix(proxy): keep password-only proxy credentials instead of dropping them when no username is set (#10720) +- **fix(executors):** the Meta AI (muse-spark-web) WebSocket send-message timeout now reports the socket's `readyState` at the moment it fires, so a "Meta AI WS timed out" failure can be told apart as either the connection never opening (`readyState=0`) or opening successfully and then going silent (`readyState=1`) — the exact ambiguity that made #10727 undiagnosable from logs alone (#10727). +- **fix(providers):** copilot-m365-web chat turns no longer surface as `(empty response)` — the type:4 invocation is aligned with the 2026-08 wire shape and now carries its type:1 Metrics follow-up in the same socket write, and the access token pre-flight-refreshes from a stored refresh_token instead of requiring a DevTools re-capture every ~75 minutes ([#10732](https://github.com/diegosouzapw/OmniRoute/pull/10732) — thanks @acc0mplish) +- **fix(catalog):** stop counting `getTokenLimit()`'s generic 128k catch-all as a known combo window, so `/v1/models` advertises the min of sourced member contexts instead of collapsing a 500k combo to 128k ([#10734](https://github.com/diegosouzapw/OmniRoute/issues/10734)) +- **fix(search):** name `/v1/search` 502s with provider id and sanitized Node cause code, without hostnames ([#10735](https://github.com/diegosouzapw/OmniRoute/issues/10735)) +- **fix(db):** pause call-log rotation and record SQLITE_CORRUPT on `/api/db/health` instead of retrying writes against a malformed pager ([#10736](https://github.com/diegosouzapw/OmniRoute/issues/10736)) +- fix(compression): skip the expensive `createCompressionStats()` pass in RTK when no message was actually compressed, matching every sibling stacked engine (#10765) +- **fix(api):** `/api/cache/stats` reported the prompt-cache LRU, which no request path ever writes to — it answered `0 hit / 0 miss, size 0` while the semantic cache served real traffic, and the Health and Usage dashboards rendered that as fact. It now reports the semantic cache's in-memory entries, with the same response shape ([#PRNUM](https://github.com/diegosouzapw/OmniRoute/pull/10769)) — thanks @Poid-ZA, who first fixed this in #9446. +- **fix(logging):** the app log is filterable and readable again. Entries from the tagged logger (`[LEVEL] [TAG] message`) were filed under the level instead of the component, and printf format strings were never applied, so `%s`/`%d` stayed literal with the values trailing behind them unlabelled — including every LiveWS connection line, where the format is deliberate hardening against injected format specifiers ([#PRNUM](https://github.com/diegosouzapw/OmniRoute/pull/10770)). +- **fix(analytics):** Claude Code (`claude`/`cc`) is a flat-rate subscription, so cost analytics reports `$0` for it instead of estimating Anthropic list prices — the metered `anthropic` API keeps its real cost, and budget/quota/routing still estimate as before ([#10774](https://github.com/diegosouzapw/OmniRoute/pull/10774)) — thanks @electrumguy +- fix(db): periodically run `wal_checkpoint(TRUNCATE)` so the SQLite WAL file shrinks on long-running servers (default 6h, override with `OMNIROUTE_WAL_TRUNCATE_INTERVAL_MS`, `0` disables) (#10781) +- fix(sse): replace LiveWS's application-only liveness check with a protocol-level `ws.ping()`/`pong` heartbeat (RFC 6455 §5.5.2) alongside the existing one, so a read-only dashboard subscriber that never sends anything survives the connection timeout — a socket that stops reading frames entirely is still reaped exactly as before (#10782) +- **fix(open-sse):** declare `supportedThinkingEfforts` (`low`/`medium`/`high`/`max`) on Ollama Cloud's `glm-5.1`, `glm-5.2`, `deepseek-v4-pro` and `deepseek-v4-flash` registry entries so the catalog's `appendSyncedEffortVariants()` pass — which only synthesizes selectable `-low`/`-high`/`-max` model ids from an already-populated `capabilities.effort_tiers` — can expose an effort selector for these reasoning-capable models, matching what `gpt-oss:20b`/`gpt-oss:120b` already had (#10788) +- **fix(resilience):** scope the same-account transport retry (#9708) out of emergency-fallback and combo hops — it was retrying the free fallback model and combo targets too, doubling upstream calls and corrupting the terminal error status on those paths. +- **fix(opencode-plugin):** respect log level in provider.models() catalog path so debug/info/warn messages are suppressed when `features.logLevel` is set to `"error"` ([#10798](https://github.com/diegosouzapw/OmniRoute/pull/10798)) — thanks @tientien17 +- **fix(providers):** Keep NVIDIA timeout probes and generic Antigravity/AGY HTTP 400 probes from poisoning credential health while preserving explicit Google geo-block handling ([#10799](https://github.com/diegosouzapw/OmniRoute/pull/10799)) — thanks @Zartharas +- fix(db): disambiguate `createProviderConnection()`'s OAuth email dedup by `providerSpecificData.profileArn` in addition to `username`, so adding a second Kiro/AWS profile with the same email creates a new connection instead of silently merging into the first (#10815) +- 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) +- **fix(images):** register OpenAI `dall-e-3` in the image registry so unprefixed `dall-e-3` (and `openai/dall-e-3`) route to OpenAI Images instead of Microsoft Designer Web, and so the chat catalog no longer lists `openai/dall-e-3` as a 128k chat model ([#10832](https://github.com/diegosouzapw/OmniRoute/issues/10832)) +- **fix(security):** Outbound URL guard now resolves IPv4-mapped IPv6 literals to their embedded address, so `[::ffff:169.254.169.254]` is refused by the unconditional cloud-metadata block like its dotted spelling; `[::]` is refused alongside `0.0.0.0` ([#10843](https://github.com/diegosouzapw/OmniRoute/pull/10843)) — thanks @ntdat812 +- fix(config): exclude cookie-auth image bridges (chatgpt-web, gemini-web) from the unprefixed model scan so a bare id never silently binds to an unofficial web bridge (#10848) +- fix(api): POST /v1/search now replies with a named `Unknown search provider: ` error (and field-named validation messages) instead of an opaque `Invalid request` for unrecognized or short-alias provider ids like `brave`/`serper` (#10849) +- **fix(api):** alias `GET`/`HEAD` `/readyz` to `/healthz` so Kubernetes readiness probes do not 404 ([#10850](https://github.com/diegosouzapw/OmniRoute/issues/10850)) +- Document the conditional management authentication and 401/403 responses for `GET /api/openapi/spec`. +- **fix(i18n):** The "Disabled" status no longer renders as the noun for a person with a disability in Japanese, Spanish, Hindi, Polish, Telugu, Urdu and both Chinese locales — 24 strings now use each catalog's existing wording (ja 無効, es Deshabilitado, hi अक्षम, pl Wyłączone, te నిలిపివేయబడింది, ur غیر فعال, zh-CN 已禁用, zh-TW 已停用) ([#10812](https://github.com/diegosouzapw/OmniRoute/issues/10812), [#10853](https://github.com/diegosouzapw/OmniRoute/pull/10853)) — thanks @ntdat812 +- **fix(skills):** Marketplace-installed skills are available to API-key-scoped requests, including existing SkillsMP and skills.sh installs ([#10854](https://github.com/diegosouzapw/OmniRoute/pull/10854)) — thanks @kriptoburak +- **fix(catalog):** `/v1/models` no longer advertises the built-in `auto/*` ids while auto routing is disabled — they were listed but rejected at request time with `Auto routing is disabled` ([#10831](https://github.com/diegosouzapw/OmniRoute/issues/10831), [#10857](https://github.com/diegosouzapw/OmniRoute/pull/10857)) — thanks @ntdat812 +- **fix(context):** Base64 file payloads (OpenAI `file` parts, Responses `input_file`, Claude `document` blocks) are budgeted like the Gemini `inlineData` path instead of being counted as prompt text — a ~1MB PDF estimated at 350k tokens and was rejected on the context limit before reaching the provider's document pipeline ([#10840](https://github.com/diegosouzapw/OmniRoute/issues/10840), [#10858](https://github.com/diegosouzapw/OmniRoute/pull/10858)) — thanks @ntdat812 +- **fix(mcp):** MCP tool calls that wait on a model provider no longer abort after 10 seconds. `omniRouteFetch` applied a single hardcoded `AbortSignal.timeout(10000)` to every internal hop, and `omniroute_route_request` — which posts to `/v1/chat/completions` and waits on the upstream provider, plus auto-combo candidate probing before a provider is even chosen — passed no signal of its own, so it inherited it. Any route slower than 10s failed from the MCP side while the identical request succeeded through the REST API. `omniroute_web_search` and `omniroute_web_fetch` in the same file already carried an explicit 60s signal, so that value is now shared by all three provider-bound calls instead of being repeated as a literal, while management reads (health, resilience, rate limits, combos, quota, usage) keep their fast-fail 10s budget so a stalled local endpoint still cannot hold a tool call open. Both budgets are overridable through `OMNIROUTE_MCP_FETCH_TIMEOUT_MS` and `OMNIROUTE_MCP_UPSTREAM_TIMEOUT_MS`, replacing the reported workaround of patching the compiled `dist/.build/next/server/chunks/*.js`; a malformed or non-positive override falls back to the default rather than disabling the timeout +- **fix(providers):** importing models with an expired API key now surfaces the credential error instead of reporting "No new models were added". The Import button posts to `/api/providers/{id}/sync-models`, which self-fetches the models route; that route does not fail on an upstream 401 but degrades to a catalog it already has, preferring the cache and using the local catalog only when there is no cache. A provider that imported successfully once therefore has a cache, so an expired key produced `{ source: "cache", warning: "Models probe failed (401) — using cached catalog" }` with HTTP 200 — and the #5460/#5465 degradation guard only recognised the `local_catalog` branch, so model-sync accepted it as a successful discovery, found every cached model already imported, and returned the empty-diff result. Retest does not go through this path, which is why it failed correctly and made the import look like a genuine "nothing to do". The existing rule — a degraded discovery must not be persisted as the synced catalog — is now applied to the branch it missed rather than special-casing 401/403, discriminating on the warning the fallback builder always attaches (an ordinary non-refresh cache hit attaches none, and model-sync always requests `refresh=true`). `isDegradedLocalCatalog` keeps its exact meaning and its existing tests +- fix(api): reject a combo update that removes every model, and store the copilot's combo targets where the router reads them (#10866) +- **fix(proxy):** proxy "Test connection" no longer reports an IPv4-only SOCKS5/SSH proxy as dead. #1255 moved every egress probe from `api.ipify.org` to `api64.ipify.org` so proxies with IPv6 egress could be tested, but `api64` is IPv6-first: a tunnel with no IPv6 route has nothing to connect to, so the probe hung until the caller's deadline and a proxy that was carrying live LLM traffic came back as a failure. Swapping the target to `api4` fixes that case and re-breaks the one #1255 fixed, so the probe now tries the targets in order instead — `api64` first, so a proxy with working IPv6 answers on the first attempt and keeps the exact behaviour #1255 introduced, including which of its addresses is reported (the egress IP is used as an identity to detect accounts of one rotation group sharing an address, so the attempts are sequential rather than raced). The attempts split the budget each call site already enforced, so no probe can take longer than it could before, and each attempt gets its own `AbortController` so exhausting the budget on an unreachable target does not abort the next one. `OMNIROUTE_PROXY_ECHO_URL` pins a single target — including a self-hosted echo — replacing the workaround of rewriting the compiled bundle after every upgrade. The relay branch of the test route still targets `api64` through `x-relay-target`, since that request egresses from the relay worker rather than the operator's tunnel +- fix(cli): warn when a .env line never takes effect, and stop swallowing an unreadable .env (#10870) +- **fix(db):** Remove stale MiMoCode provider configuration, including the legacy `mcode` alias, left after provider retirement while preserving historical usage and call logs ([#10873](https://github.com/diegosouzapw/OmniRoute/pull/10873)) — thanks @Zartharas +- **fix(sse):** `getResetAwareProvider()` and the auto-combo quota lookup in `combo.ts` now canonicalize the provider id via `resolveProviderId()` before calling `getQuotaFetcher()`, so a fetcher registered under a provider's canonical id (e.g. `ollama-cloud`, `codex`) is found for combo targets stored under an alias spelling (e.g. `ollamacloud`, `cx`) instead of silently degrading reset-aware/reset-window/auto quota-aware routing to plain priority ordering (#10877) +- **fix(provider-health):** Keep unsupported 404/405 validation probes neutral so they do not poison stored credential health or scheduler failure state, while still honoring per-connection health-check pacing ([#10878](https://github.com/diegosouzapw/OmniRoute/pull/10878)) — thanks @Zartharas +- **fix(antigravity):** map Gemini 3.7 Flash tier ids (`gemini-3.7-flash-high/medium/low`, bare `gemini-3.7-flash`) to the upstream `gemini-3.7-flash-tiered` model id Google's Cloud Code endpoint expects, and configure per-tier thinking budgets ([#10882](https://github.com/diegosouzapw/OmniRoute/pull/10882)) — thanks @adevwithpurpose +- **fix(memory):** enable agent memory save/update via MCP tools (`memory_save`/`update`/`search`/`delete` builtins with per-provider schemas, `apiKeyId` optional with caller-principal fallback) and gate server-side memory builtin injection to non-stream requests only ([#10887](https://github.com/diegosouzapw/OmniRoute/pull/10887)) — thanks @Egorich-print +- **fix(perplexity-web):** make the built-in-search hint appended to every system message opt-in via `OMNIROUTE_PPLX_SEARCH_HINT` (off by default) — Perplexity's answer engine searches anyway, and the hint leaked into replies as meta-commentary for coding clients ([#10902](https://github.com/diegosouzapw/OmniRoute/pull/10902), extracted from [#8634](https://github.com/diegosouzapw/OmniRoute/pull/8634)) — thanks @danscMax +- **fix(providers):** the loopback readiness gate no longer memorizes a failed probe — the next caller after 30s starts a fresh probe, and a readiness failure is logged once per probe instead of once per caller ([#10903](https://github.com/diegosouzapw/OmniRoute/pull/10903)) +- **fix(relay):** the Cloudflare proxy-relay worker now resolves `x-relay-path` through the shared `resolveRelayTarget()` guard instead of concatenating it onto the validated target. PR #4643 and its follow-up applied that guard to the Deno and Vercel workers; the Cloudflare generator, ported separately from upstream `decolua/9router` PR #1360, kept `fetch(targetBase + relayPath)`. Validating `x-relay-target` and then concatenating is not sufficient — the path re-points the request past the host that was just checked, through userinfo (`/x@evil.com`), a backslash (`\evil.com`), or a protocol-relative path (`//evil.com/x`). The guard is embedded verbatim under a literal `const resolveRelayTarget =` binding so the hardcoded call site still resolves when the SWC-minified standalone build mangles the source function's own name (#6149), and the new regression test pins that property for this worker by renaming the embedded function and re-evaluating the emitted source. The auth check and the private/loopback target guard are unchanged +- **fix(build):** the `next` Docker image no longer crashes on boot with `ReferenceError: require is not defined in ES module scope`. The standalone `server.js` is CommonJS, but the `postbuild` colocate step was re-adding `"type":"module"` to the standalone root `package.json` (undoing `assembleStandalone`'s strip) to make its ESM worker bundles load. The `type:module` scope is now written per-worker-directory instead of on the root, so `server.js` stays CommonJS while the workers stay ESM ([#10936](https://github.com/diegosouzapw/OmniRoute/pull/10936), fixes [#10933](https://github.com/diegosouzapw/OmniRoute/issues/10933)) — thanks @arminanton +- fix(cli): always emit limit.output in generated OpenCode config so schema validation passes for metadata-less models (#10940) +- **fix(relay):** the private/loopback guard the three proxy-relay workers embed no longer misses four host spellings, and now lives in one place instead of three byte-identical inline copies. Driving `new URL(target).hostname` the way the workers do, the previous guard allowed `::` (the unspecified address, which reaches a service bound to the IPv6 loopback), `localhost.` (the FQDN root dot defeated the exact match and every `.localhost`/`.local`/`.internal` suffix rule, so `svc.internal.` slipped too), `::127.0.0.1` (the deprecated IPv4-compatible form — only `::ffff:` was checked), and `feb0::1` (link-local is `fe80::/10`, spanning `fe80`–`febf`, but only the literal `fe80:` spelling matched). The policy moved to `src/lib/proxyRelay/privateHostname.ts` and is embedded verbatim via `Function#toString` under a literal const name, the same mechanism `resolveRelayTarget` already uses for these workers, so a minified standalone build cannot break the call site (#6149). Nothing previously blocked is now allowed. Severity is low — reaching a worker needs the `x-relay-auth` secret and these are edge runtimes where loopback has nothing listening — but the suffix-rule bypass held regardless of runtime +- **Account rotation:** make `fallbackStrategy: "least-used"` actually rotate. The strategy sorts on `lastUsedAt` but never wrote it — only the round-robin branch committed — so on a pool where every `last_used_at` was still `NULL` the tie-break fell through to `priority` and returned the same connection on every dispatch ([#10945](https://github.com/diegosouzapw/OmniRoute/issues/10945)). +- **Desktop auto-update (Windows):** stop the in-app updater 404ing on every release. NSIS used electron-builder's default artifact name, whose spaces GitHub rewrites to `.` on upload while `latest.yml` keeps `-`, so the manifest pointed at `OmniRoute-Setup-X.Y.Z.exe` while the published asset was `OmniRoute.Setup.X.Y.Z.exe`. The name is now set explicitly to the dot form the asset already has, so nothing published changes name ([#10947](https://github.com/diegosouzapw/OmniRoute/issues/10947)). +- Preserve explicit plaintext reasoning when a Responses reasoning item also carries opaque provider state (rare OpenCode Go `deepseek-v4-flash` responses). Mixed plaintext + opaque input is projected onto the target transport: plaintext targets keep portable text, opaque targets keep provider state. Opaque-only reasoning is dropped when the selected target cannot replay it, allowing cross-model conversations to continue. (#10949, #10959) +- **fix(catalog):** preserve provider-declared reasoning effort tiers instead of replacing them with generic defaults ([#10953](https://github.com/diegosouzapw/OmniRoute/pull/10953)) — thanks @xz-dev +- fix(cli): combo create accepts --models and no longer creates empty combos (#10954) +- fix(cli): resolve $ref path params and add PATCH combos requestBody in generated API commands (#10955) +- 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)) +- fix(sse): combo diagnostics no longer truncate `exhausted_connection` entries to a hardcoded `provider: "unknown"` with the provider prefix eaten by an 8-char slice — the real provider id is preserved and only the connection id is truncated (#10967) +- fix(sse): combo terminal failures caused entirely by quota/account-balance exhaustion (including a durable HTTP 403 `insufficient_quota` / `AUTHZ_INSUFFICIENT_BALANCE`) now stamp a stable `quota_exhausted` diagnostics reason with a `switch-combo` recovery hint instead of the misleading default `retry` action (#10966) +- **fix(search):** skip catalog-default SearXNG `http://localhost:8888/search` so Docker/K8s search does not ECONNREFUSED then 502 into the next provider ([#10976](https://github.com/diegosouzapw/OmniRoute/issues/10976)) +- fix(command-code): surface reasoning-only output as content when a model emits no text-delta (#10986) +- **fix(ci):** clear inherited `release/v3.8.50` quality-gate reds on the X Search PR: drop the stale `copilot-m365-web.ts:330` public-creds allowlist, document six missing env vars, register four covering Stryker tap tests, prune leftover ESLint suppressions, replace the phantom `@/lib/db/connections` Utilization import with `getProviderConnectionById`, and fix open-sse/dashboard typecheck regressions in freebuff, browser-backed chat, auth, health matrix, and Monaco ([#10988](https://github.com/diegosouzapw/OmniRoute/pull/10988)). +- **fix(ci):** clear remaining `release/v3.8.50` unit-shard reds on the X Search PR: pin `onnxruntime-node` to the transformers 1.24.3 copy, rebaseline OpenAPI coverage, sync goldens/i18n, honor eye-hidden no-auth models across provider aliases, await rejected-request call-log writes, absorb catalog event-loop shard contention in #9147, and align inherited tests with advisory context estimates, #10501 combo terminal-status aggregation, and current catalog/auth behavior ([#10988](https://github.com/diegosouzapw/OmniRoute/pull/10988)). +- **Static model catalog for v0-vercel-web:** seed a static catalog for the v0-vercel-web web-cookie provider (v0-1.0-md, v0-1.5-lg, v0-1.5-md) so its dashboard "Available Models" / "Import from /models" UI serves a usable list instead of falling through to the route's 400 "does not support models listing" ([#10990](https://github.com/diegosouzapw/OmniRoute/issues/10990)). +- fix(providers): mark the blackbox provider deprecated — api.blackbox.ai returns HTTP 404 on every path variant (sweep 2026-08-21), so the public inference surface is dead and the catalog entry now carries a deprecation notice. ([#10997](https://github.com/diegosouzapw/OmniRoute/issues/10997)) +- fix(providers): validate Dify keys against its native /v1/chat-messages endpoint (#11002) +- **fix(accounts):** `markCooldown` now carries the failure origin (`transient` vs `terminal`) — transient 429/network only cools down, repeated terminal failures evict and are skipped by `pickAccount` until a success or operator clear ([#11008](https://github.com/diegosouzapw/OmniRoute/pull/11008)) — thanks @maxmad64bis +- **fix(providers):** route terminal `testStatus` writes (`banned`, `deactivated`, `credits_exhausted`) through a single origin-aware passage — probe failures are recorded but never deactivate the connection ([#11009](https://github.com/diegosouzapw/OmniRoute/pull/11009)) — thanks @maxmad64bis +- **fix(codex):** drop non-standard `codex.*` SSE events by default so OpenAI SDK / Codex CLI `/v1/responses` clients are not 502'd by `event: codex.rate_limits` ([#11014](https://github.com/diegosouzapw/OmniRoute/issues/11014)) — thanks @RaviTharuma +- **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 +- **fix(startup):** log `Credential health scheduler disabled` when `OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK` is set instead of lying with `started` ([#11016](https://github.com/diegosouzapw/OmniRoute/issues/11016)) — thanks @RaviTharuma +- **docs(api-keys):** document that unset `DEFAULT_RATE_LIMIT_PER_DAY` is unlimited (#2289), not a hidden 1000/day cap ([#11017](https://github.com/diegosouzapw/OmniRoute/issues/11017)) — thanks @RaviTharuma +- **fix(webhooks):** remove 3 declared-but-never-emitted events (`provider.error`, `provider.recovered`, `combo.switched`) from `WebhookEvent` — catalog now `request.completed | request.failed | quota.exceeded | test.ping`; `POST /api/webhooks` and `PUT /api/webhooks/[id]` reject ghost values with 400; OpenAPI webhook description updated across 43 locales ([11050](https://github.com/diegosouzapw/OmniRoute/pull/11050)) +- fix(providers): filter Perplexity model import to the Sonar family so Agent-API catalog ids stop surfacing as routable chat models (#11060) +- **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 +- **fix(resilience):** filter chat connection selection by each connection's *synced* model inventory on multi-host self-hosted providers (`ollama-local`, `lm-studio`, `vllm`, …), so a request for a model only one host advertises is pinned to that host instead of failing over onto a host that never had it ([#11089](https://github.com/diegosouzapw/OmniRoute/issues/11089)) +- fix(install): make the ONNX dependency chain optional so Termux/Android installs succeed again (#11095) +- **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)) +- **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=`) 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)). +- **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)). +- 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)) +- **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 +- **fix(sse):** parallel `function_call` items in a Responses API stream (e.g. several tool calls dispatched in the same turn) now each get a stable, distinct `index`/`id` when translated to Chat Completions streaming deltas, instead of colliding on index 0 and tripping strict stream parsers with `Expected 'id' to be a string.` ([#11144](https://github.com/diegosouzapw/OmniRoute/pull/11144)) +- **fix(analytics):** `opencode-go` is now classified as a flat-rate subscription, so cost analytics shows $0 for it instead of billing every call at the underlying model’s metered rate — it resells GLM, Kimi, Grok, DeepSeek, MiniMax, Qwen and GPT-5.x under one flat monthly fee, which made the overstatement large rather than marginal ([#11149](https://github.com/diegosouzapw/OmniRoute/pull/11149)) — thanks @electrumguy +- fix(dashboard): keep `open-sse/config/providerRegistry.ts` free of `node:net` so the provider detail client bundle builds again — the host classification moved to a platform-free `src/shared/network/privateHost.ts` with a pure-JS `isIP` equivalent, leaving the #11122 routing behaviour unchanged (#11154) +- **Combo create:** creating a routing combo without any model is now refused (`400`) — the CLI requires `--models`/`--model` on `combo create`, matching the dashboard which already rejected empty combos. +- **fix(resilience):** a missing-model `404` on a provider that declares `passthroughModels: true` in the shared registry (novita, uncloseai, orcarouter and 37 others) now locks out only that model instead of cooling the entire connection — `hasPerModelQuota()` previously read only the open-sse registry and the local/self-hosted families ([#11165](https://github.com/diegosouzapw/OmniRoute/pull/11165)) — thanks @yourspraveen +- **fix(routing):** a custom `openai-compatible-*` / `anthropic-compatible-*` connection pointing at a keyless self-hosted backend (llama.cpp, Ollama, vLLM started without an API key) now stays in the `auto/*` candidate pool instead of being silently dropped by the credential gate — for those IDs "no credential" is the normal configuration, not an unconfigured connection ([#11180](https://github.com/diegosouzapw/OmniRoute/pull/11180)) — thanks @marcs7 +- **fix(routing):** the Routing tab's "last known good provider" toggle now actually takes effect — `lkgpEnabled` was persisted and the `lkgp` strategy guarded on it, but the setting was never forwarded into the `RoutingContext` built in `resolveAutoStrategyOrder()`, so `context.lkgpEnabled` was always `undefined` and the off-switch was unreachable ([#11181](https://github.com/diegosouzapw/OmniRoute/issues/11181)) +- **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 +- **fix(providers):** Antigravity OAuth marks connects with no Cloud Code projectId as degraded instead of a false "Connected"; BYOP detection at connect time, auto-disable of confirmed-missing accounts, and selection-side rotation ([#11284](https://github.com/diegosouzapw/OmniRoute/issues/11284)) +- **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 +- **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)) +- **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)) +- **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)) +- **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)). +- **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)) +- **fix(video-bridge):** fall back to the deterministic active-window midpoint when a one-frame scene-aware budget cannot preserve both timeline ends; a real FFmpeg fixture matrix now covers rapid cuts, gradual changes, static and short clips, and detector failure ([#11344](https://github.com/diegosouzapw/OmniRoute/pull/11344)). +- **fix(translator):** Codex Responses tool calls translated for Claude clients no longer emit a duplicate `tool_use` block with the same ID and an empty name, preventing Claude Code from terminating with `No such tool available` ([#11347](https://github.com/diegosouzapw/OmniRoute/pull/11347)) +- **fix(video-bridge):** burn high-contrast timestamps into every bounded contact-sheet cell and add a real-model A/B harness whose promotion verdict stays `HOLD` until token, latency, and quality evidence is actually executed ([#11350](https://github.com/diegosouzapw/OmniRoute/pull/11350)) +- **fix(video):** fingerprint protected Video Bridge bytes, coalesce concurrent work, and fail open when the bounded TTL/LRU result cache is unavailable or corrupt ([#11362](https://github.com/diegosouzapw/OmniRoute/pull/11362)) +- **fix(catalog):** keep large `/v1/models` builds responsive by reusing the build-local capability snapshot throughout enrichment and Auto-Combo preparation, yielding cooperatively while constructing virtual candidate pools, and avoiding unrelated synchronous database diagnostics on the cache-TTL read path ([#11367](https://github.com/diegosouzapw/OmniRoute/pull/11367)) +- **fix(video):** apply the caption-frame cap after bounded visual deduplication, preserve first/final candidates plus small high-contrast motion and text changes, and version the dedup policy in result-cache identity ([#11382](https://github.com/diegosouzapw/OmniRoute/pull/11382)). +- **Live dashboard:** honour the WebSocket port reported by `/api/v1/ws?handshake=1` instead of the port compiled into the bundle, so a `LIVE_WS_PORT` override reaches prebuilt Docker/npm images and Combo Studio Live connects behind a reverse proxy ([#11331](https://github.com/diegosouzapw/OmniRoute/issues/11331)). +- **fix(dashboard):** Model Database sync interval slider ticks now match the thumb position — checkpoint-space slider with magnetic snap on release ([#11394](https://github.com/diegosouzapw/OmniRoute/pull/11394)) — thanks @An0nym0us92 +- **fix(api-manager):** Allowed Combos can now be restricted to zero entries: **All** is stored explicitly as `combo/*`, while **Restrict** with no selection saves an empty allowlist that denies Combo routes without blocking direct models. Existing keys are migrated to preserve their previous allow-all behavior. +- fix(build): tolerate a same-realpath symlink or stale-typed dest in the standalone bundle assembler, fixing non-deterministic `ERR_FS_CP_EINVAL`/`ERR_FS_CP_DIR_TO_NON_DIR` crashes under heavy concurrent build I/O +- **fix(auto):** rate-limit `auto/ matched no connected models` warnings to once per minute per label (`open-sse/services/autoCombo/virtualFactory.ts`) +- fix(cli): drop the orphaned `resolveOpencodeConfigDir` re-export from `cliRuntime` — it lost its last consumer in #10246 and diverged from the canonical resolver by one directory level (#9985) +- fix(ci): make `Build (advisory)` produce a signal again — pinned to a hosted runner with the swap/heap provisioning `Fast Production Build` proves sufficient, and scoped to fork PRs, which are the only ones `build.yml` cannot cover (72 of the last 100 PRs into `release/**`) +- **fix(api):** hash API keys in the `/v1/models` catalog cache Map key so heap dumps cannot leak bearer tokens (`src/app/api/v1/models/catalogCache.ts`) +- **fix(providers):** register live OpenRouter Gemini Embedding 2 ids (`google/gemini-embedding-2` and `google/gemini-embedding-2-preview`, 3072-d) in the curated embeddings catalog so `GET /v1/models` and `GET /v1/embeddings` list the ids that already serve — thanks @RaviTharuma +- **fix(translator):** merge consecutive same-role contents in direct Claude to Gemini request translation to prevent upstream HTTP 400 errors +- **fix(cli):** `omniroute update` now finds npm on Windows. It called `execFile("npm", …)` with no shell, and on Node ≥ 24 a `.cmd` wrapper cannot be spawned that way (nodejs/node#52554) — while a bare `npm` can also resolve to an extensionless shim `CreateProcess` refuses. The result was `✖ Could not check latest version. Is npm available?` in a terminal where `npm view omniroute version` worked fine, so the updater was unusable on Windows even though nothing was wrong with the install. This is the same class as #5379/#5542, which fixed the server-side calls; the CLI entry points were missed because they are plain `.mjs` and cannot import the TypeScript helper. `bin/cli/npm-exec.mjs` now states the same rule for them: `npm.cmd` plus a shell on win32, no shell anywhere else. Both npm lookups in `update.mjs` (version and changelog) pass a literal argv array, so enabling the shell cannot splice a runtime value into the command line — a test asserts that and fails if a future edit interpolates one. (#11335) +- **fix(cline):** Preserve client-supplied Cline task IDs and omit the header when clients provide none, preventing request-scoped proxy IDs from being reported as tasks. +- 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. +- 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 +- **fix(catalog):** derive combo reasoning-effort tiers from the exact runtime-selectable connection scope, intersecting dynamic, pinned, allowlisted, and compatible provider-node evidence while failing closed on unknown capabilities. +- fix(combo): evict in-memory session-stickiness bindings when a combo disables stickiness, so stale pins stop overriding the declared priority order until TTL/restart +- fix(combo): resolve effort-suffixed command-code variants (e.g. `deepseek-v4-flash-max`) to their base model for capability lookups, so tool-bearing combo requests keep the declared priority order instead of reordering behind models with confirmed capabilities +- **fix(db):** the `compression_run_telemetry` retention sweep now actually deletes expired rows. Its cutoff was computed in epoch seconds while the column stores epoch milliseconds, so `WHERE timestamp < cutoff` never matched and the table added by #6848 to bound `storage.sqlite` growth was unbounded in practice. Same unit mismatch as #9625, which corrected the sibling `domain_cost_history` sweep and missed this call site +- **fix(compression):** use `pathToFileURL` in `compressionWorkerPool` so bundlers (Webpack / Turbopack) do not attempt static asset resolution of missing `compressionWorker.js` during build +- **fix(db):** database settings API no longer returns HTTP 500 on SQLite builds compiled without the optional `dbstat` virtual table (sql.js/WASM); per-table sizes degrade to 0 instead of failing the whole stats call +- fix(discovery): parse upstream reasoning tiers nested under metadata.reasoning.supported_efforts (neuralwatt /v1/models shape) so synced openai-compatible models advertise effort aliases +- **fix(ops):** Docker HEALTHCHECK probes lightweight `/healthz` instead of `/api/monitoring/health` so a busy event loop does not mark the container Unhealthy (`scripts/dev/healthcheck.mjs`) +- **fix(api):** `/v1/embeddings` 400s for native `gemini-embedding-2` now name the working OpenRouter ids (`openrouter/google/gemini-embedding-2` and the preview alias) instead of only `No credentials for embedding provider: gemini` — thanks @RaviTharuma +- **fix(sse):** keep Codex/Anthropic quota headers under the upstream forwarding budget; drop `x-codex-turn-state` and raise the 768-byte cap (`open-sse/handlers/chatCore/responseHeaders.ts`) +- **fix(usage):** z.ai/GLM coding-plan subscription keys now render their quota cards again, with absolute credits. Z.ai's `/api/monitor/usage/quota/limit` switched these keys from `TOKENS_LIMIT` to `CREDIT_LIMIT` rows (same `unit`/`number` semantics: unit=3/number=5 → 5-hour window, unit=6/number=1 → weekly), and the parser only matched `TOKENS_LIMIT`/`TIME_LIMIT`, so both rows were dropped and the subscription card rendered empty. `CREDIT_LIMIT` is now accepted alongside `TOKENS_LIMIT`, and when the row carries absolute credit fields (`usage`/`currentValue`/`remaining`) they are preferred over the percent-only scale, so the card shows `3341 / 28000` like z.ai's own dashboard instead of `11 / 100` +- **fix(auth):** a connection's `lastError` now names the real upstream failure instead of the bare string `Provider error`. `markAccountUnavailable` kept the reason only when it was already a string, so every other shape collapsed to that literal — and the shape that matters most is not a string: a failed `fetch` arrives as `TypeError: fetch failed` with the actionable part on `error.cause.code`, which means a wrong port, a firewall, a DNS failure and a blocked proxy all looked identical in the dashboard and in the console line. `describeUpstreamFailure` (in `src/shared/utils/upstreamError.ts`, reusing the `extractErrorMessage` that already parsed provider bodies) reads Error messages and appends the transport code when the message does not already carry it, reads the usual provider JSON shapes (`error.message`, `message`, string `error`, `detail`, `errors[]`), and falls back to the code alone before giving up. It never serializes the error object wholesale, so a request body or header attached to an error cannot leak into the stored reason — pinned by a test. +- **fix(live-ws):** the Live dashboard socket can now be pointed at a reverse proxy without rebuilding the image. `NEXT_PUBLIC_*` is inlined at BUILD time, so a prebuilt Docker or npm image never carries an operator's `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL` — which is exactly why the browser discovers the socket through `/api/v1/ws?handshake=1` instead. The server side of that handshake, however, read only the `NEXT_PUBLIC_`-prefixed name, so it had nothing to echo: behind Traefik the dashboard kept dialling `wss://:20132/live-ws` and sat on "Live disabled — WebSocket disconnected. Showing last known state." `LIVE_WS_PUBLIC_URL` is now read at runtime alongside the existing `LIVE_WS_HOST` / `LIVE_WS_PORT`, and the prefixed name stays supported as the fallback, so deployments that already set it are unaffected. Only `ws://` and `wss://` values are accepted, matching the guard the client already applies. (#11331) +- **fix(sse):** MiniMax music models now generate audio instead of failing with `Unsupported music format: minimax-music` — the provider entry was registered in the music registry (and advertised by `/v1/models`), but `handleMusicGeneration` had no branch for its format, so every `minimax/*` music request fell through the dispatch chain to a 400. Adds the missing dispatch: a single synchronous POST with the `base_resp` envelope check (a non-zero `status_code` arrives on HTTP 200 too), `data.status` handling (an unfinished generation is reported instead of polled — the operation has no task id and no query endpoint), `url` and `hex` output formats (hex normalized to base64), `mp3`/`wav`/`pcm` containers via `audio_setting`, and the regional endpoint through the per-connection base-URL override, which is also the only host that accepts `aigc_watermark`. The registry entry gains the generation and cover model ids it was missing and drops a query URL that does not exist for this operation. Regression guard: `tests/unit/minimax-music-generation.test.ts` (9 tests). +- **fix(models):** honor `MODELS_DEV_SYNC_ENABLED=0` as a hard kill switch over the dashboard setting so a wedged `/healthz` / UI can be recovered without HTTP (`src/lib/modelsDevSync.ts`) +- **fix(providers):** when `OPENCODE_SYNTHESIZE_CLI_HEADERS=true`, a non-CLI client User-Agent (e.g. `curl/8.5.0`, SDKs) on opencode-go/opencode-zen/opencode-free requests is now REPLACED with the synthesized `opencode-cli/1.0.0` instead of being honored — opencode.ai's free tier (`/zen/v1`) returns `FreeUsageLimitError` 429 for generic client UAs egressing from datacenter IPs, which made the #5997 CLI-identity synthesis ineffective for non-CLI clients. Client UAs already matching `opencode-cli/…` are preserved (the real CLI's versioned identity stays intact); all other client-supplied `x-opencode-*` headers keep client-wins. Regression guard: `tests/unit/opencode-cli-headers-synthesis-5997.test.ts` (7, incl. non-CLI UA replaced + CLI UA preserved). (#5997 follow-up) +- **OpenCode config merge:** stop `mergeOpenCodeConfig` splaying a malformed `provider` block into index keys. The root was already guarded against a non-object; the `provider` branch it spreads one level down was not, so an existing `"provider": ["a", "b"]` merged to `{"0": "a", "1": "b", …}`. Its sibling `mergeOpenCodeConfigText` already refuses the same input. +- **fix(models):** a model synced from a provider's own `/models` discovery is now enforced at its real context window immediately, instead of waiting up to 24h for the Feature 5004 reconciler's next tick. The request-time token-limit chain resolves the window from `auto:discovery` overrides, which previously were only written at startup and on a 24h interval — so any model synced mid-cycle (models.dev not indexing it yet, no static registry entry) fell through to the provider's static `defaultContextLength` (128K for OpenRouter) while `/v1/models` simultaneously advertised the real window from the same discovery data. Measured: `openrouter/stealth/ox-alpha` advertised `context_length: 1048576` but rejected requests over 128K with `context_length_exceeded` for a full day after its sync. The reconcile now also runs opportunistically (debounced, fire-and-forget) right after a synced catalog write changes. Companion fix: discovery now captures the vendor-declared `reasoning.default_effort` (e.g. OpenRouter `stealth/ox-alpha` declares `max`, normalized to `xhigh`) as `defaultThinkingEffort`, and the OpenAI dispatch path injects it when a request carries no reasoning field of any shape — the lowest-priority default behind a `-{effort}` suffix alias and a static `ModelSpec.defaultReasoningEffort` — so a reasoning model that returns an empty response without an explicit effort gets the vendor default instead of `upstream_empty_response`. +- **fix(providers):** Claude Code / CC-protocol-compatible clients sending `cache_control` with no `ttl` on the native Claude OAuth path (`claude`/`cc`) now default to the 1h extended cache TTL instead of silently falling back to Anthropic's 5-minute default, even though the 1h beta is always negotiated on this path — thanks @jeff-alves +- **fix(electron):** desktop window stays hidden on Windows because the embedded Next.js server binds to the machine hostname instead of loopback ([#PENDING](https://github.com/diegosouzapw/OmniRoute/pull/PENDING)) +- **fix(executors):** OpencodeExecutor rotates (or retries once on a single-account direct path) on upstream 400 empty-body rejections — malformed completion envelopes with no error field were propagated as success and killed client sessions. Bounded +1 attempt per request; body reads are conditioned on status 400 so successful/streaming responses are never buffered. 400s carrying an error field keep propagating immediately. +- **fix(cli):** recognize native `opencode.jsonc` files in OpenCode detection, generated-provider setup, and dashboard save/apply flows; preserve unrelated JSONC comments and provider settings, write updates back to the selected file, and refuse to overwrite invalid config ([#10227](https://github.com/diegosouzapw/OmniRoute/issues/10227)) — thanks @tito13kfm +- fix(i18n): complete Vietnamese translations for recently added UI strings (#9985) +- fix(api): repair broken `@/lib/db/connections` import in the usage utilization route that failed the production build (#10939 follow-up) +- chore(docs): regenerate PROVIDER_REFERENCE and refresh README diagram SVGs to the real provider count (347) +- chore(lint): prune ESLint suppressions orphaned on the release branch +- **fix(build):** repair the broken Turbopack production build, the red lint gate and a runtime crash on `release/v3.8.50`. Six independent module-level defects, each from a different PR, had accumulated because the `Build` CI job is advisory rather than blocking: a lost closing brace in `modelSelectModalHelpers.ts` that swallowed `PROVIDER_TEST_CHUNK_SIZE` into a function body (#9011); `handleFalVideoGeneration` imported twice in `videoGeneration.ts` after the provider-neutral Fal module superseded the standalone handler (#9982 over #9969); `catalog.ts` still re-exporting and calling the injectable stale-while-revalidate policy that #9199 deliberately replaced with a fixed 30 s bound when it landed on top of #8728 — the consumer and the #8728 test suite were never realigned; two dangling statements left in `catalogCache.ts::scheduleBackgroundRefresh` referencing undeclared `inFlight`/`promise`, which made **every** stale-while-revalidate read throw a `ReferenceError` at runtime (a defect the build never caught, surfaced here by the realigned test); a generated wasm-bindgen sidecar URL in `tinycmsSigner.ts` that Turbopack resolves at build time even though the WASM module ships inlined as base64 (#8736/#10087); `conolDiscovery.ts` importing `getProviderOutboundGuard` from `outboundUrlGuard` instead of the sibling `outboundUrlGuardPolicy` module that actually exports it (#8974) — fixed on the consumer side, since re-exporting it would put a `@/`-aliased import into the module the packaged CLI loads without a tsconfig (#7682); and an unbalanced brace in `tests/unit/db-adapters/driverFactory.test.ts` where a new case was inserted between the preceding test's `finally` block and its `});`, so the whole file stopped parsing and the SQLite driver-cascade coverage silently stopped running since 2026-08-11 (#9173). +- **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. +- **fix(db):** the sql.js fallback now publishes the database atomically — temp file in the same directory, `fsync`, then `rename()` — instead of rewriting it in place with `writeFileSync`. sql.js has no incremental write path, so every save rewrote the whole image through an `O_TRUNC` open: for the duration of the write the on-disk database was 0 bytes and then partial, a window that scales with database size and recurs on every save. Unlike better-sqlite3 / node:sqlite, that window is not covered by SQLite's locking protocol, so it was visible to every OTHER process reading the same file (a backup job, a metrics exporter, an operator running `sqlite3`), which got `SQLITE_CORRUPT` — "database disk image is malformed" — while `PRAGMA integrity_check` passed moments later. It also closes a total-loss window: a crash mid-write used to leave the real database truncated, and now only leaves a stale temp file ### 📝 Maintenance @@ -792,6 +1138,83 @@ _Living section — regenerated 2026-08-12 from all cycle commits (cycle open `e - **deps:** bump electron from 43.2.0 to 43.3.0 in /electron ([#10042](https://github.com/diegosouzapw/OmniRoute/pull/10042)) — thanks @app/dependabot - **maint(release):** 45 direct pushes to the release branch with no PR ref — base-red and quality-gate repairs, i18n string completion and stream/type fixes (quality ×6, i18n ×5, deps ×3, agentrouter ×3, providers ×2, release ×2, security ×2, logging ×2) - **maint(repo):** 29 chore/ci/test/docs commits rolled up — quality baselines, mutation registration, CI re-triggers, doc restructure and repo hygiene (#10187, #10189, #10190, #10193, #10196, #10203, #10204, #10205, #10207, #10210, #10236, #10318) +- **docs(auth):** distinguish dashboard sessions, `oma_live_…` Access Tokens, manage-scoped API keys, and inference keys ([#7786](https://github.com/diegosouzapw/OmniRoute/issues/7786)) +- **docs(ops):** document Kubernetes probe recommendations — TCP (or soft HTTP) liveness, HTTP `/healthz` readiness, avoid `/api/monitoring/health` as kubelet liveness ([#10297](https://github.com/diegosouzapw/OmniRoute/pull/10297)) — thanks @RaviTharuma +- **docs(docker):** spell out that `:latest` tracks the highest **published** stable SemVer (not git `main`), and that GitOps should pin `X.Y.Z` ([#10317](https://github.com/diegosouzapw/OmniRoute/issues/10317)) +- **docs(backend):** document that memory extraction, skills injection, and token refresh share the request event loop, plus dashboard kill switches ([#10349](https://github.com/diegosouzapw/OmniRoute/issues/10349)) +- **docs(docker):** document default SQLite as single-replica / HA-unsupported, including Recreate and HEALTHCHECK session blast radius ([#10350](https://github.com/diegosouzapw/OmniRoute/issues/10350)) +- **docs(backend):** document that pre-write SQLite backups (including models.dev pricing) are throttled to once per 60 minutes and can be disabled with `DISABLE_SQLITE_AUTO_BACKUP` ([#10351](https://github.com/diegosouzapw/OmniRoute/issues/10351)) +- **fix(tests):** drain three base-reds on the release branch — the Vietnamese locale regained parity with English (6 keys added), the chatCore SSE test now asserts the comment-free default that #10539 introduced instead of the trailer it replaced, and the Antigravity cloudcode test asserts the missing-messages guard it is named for instead of a `/ok/` regex that only ever matched the "ok" inside `: x-omniroute-tokens-in` ([#10704](https://github.com/diegosouzapw/OmniRoute/pull/10704)) +- chore(security): remove the unused `enforceSecrets()` duplicate of the boot secret check and pin the live `enforceWebRuntimeEnv()` wiring with a regression test (#10775) +- fix(quality): register GrokBuildToolCard.tsx react-hooks/set-state-in-effect suppression (dropped in #10778's uncommitted fix) +- **docs:** Custom combos are only invoked by their exact name in the `model` field — `auto` remains a separate zero-config router, and `openrouter/auto` is a paid OpenRouter product, not an alias ([#10779](https://github.com/diegosouzapw/OmniRoute/pull/10779)) — thanks @maxmad64bis +- chore(startup): remove `src/server-init.ts` (183 lines, never imported — the boot path is `src/instrumentation-node.ts`) and correct four `"called from server-init.ts"` comments left pointing at the dead entry point (#10780) +- fix(quality): rebaseline file-size for #10859's own modelCapabilities.ts/commandCode.ts growth (missed at merge time) +- **docs(openapi):** document the `GET` and `PUT` operations on `/api/combos/{id}`, and add an operation-level coverage floor so a missing verb can no longer hide behind a path that already counts as covered ([#10875](https://github.com/diegosouzapw/OmniRoute/pull/10875)) +- fix(quality): bump EXPECTED_FEATURE_FLAG_COUNT to 52 for #10889's own new flag (missed at merge time) +- **test(db):** replace three empty `test.skip` placeholders in the critical DB-state suite with real assertions — `resetDbInstance` must swap the singleton while the on-disk row survives, the on-disk DB must open in WAL journal mode, and `db_meta` must hold the seeded `schema_version` — so a regression in any of those invariants can no longer pass as silently green ([#10906](https://github.com/diegosouzapw/OmniRoute/pull/10906)) +- **docs(docker):** document runtime RAM for coding-agent `/v1/responses` (image default 1 GiB heap is dashboard-only; 8–12 GiB heap for agents) ([#10982](https://github.com/diegosouzapw/OmniRoute/issues/10982)) +- **docs(database):** align the SQLite cache guide with the 65,536 KiB runtime default, supported 1–1,000,000 KiB range, and live Settings application behavior ([#11018](https://github.com/diegosouzapw/OmniRoute/issues/11018)) +- **docs(docker):** document N independent `DATA_DIR`s as the supported large `/v1/responses` scale-out (one V8 heap ≠ host RAM; do not `replicas>1` on one SQLite file) ([#11024](https://github.com/diegosouzapw/OmniRoute/issues/11024)) — thanks @RaviTharuma +- fix(quality): rebaseline file-size for modelCapabilities.ts (1016->1072) drift from merged tip fixes (#11034 et al) +- fix(quality): register `tests/unit/authz/oauth-autoimport-local-only.test.ts` in stryker `tap.testFiles` (residual of #11053) +- chore(quality): drain two `release/v3.8.50` base-reds — refresh the drifted doc counts (159 migrations, 56 free-forever providers, 40 free-tier pools, incl. the 42 `llm.txt` locale mirrors) and move `uncloseai-noauth.test.ts` to a collected path so the UncloseAI no-auth regression guard actually runs (#11160) +- **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)) +- **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)). +- **ci(changelog):** replace the broad removal bypass with an exact, hash-bound reconciliation ledger and bind merge-train checks to their requested release base ([#11345](https://github.com/diegosouzapw/OmniRoute/pull/11345)). +- **docs(readme):** reconcile live v3.8.50 provider, free-tier, CLI, routing, test, + community, sponsor, acknowledgment, and SVG metrics with their audited source + denominators, including a deduplicated OmniRoute-in-Action snapshot and distinct + contributor rankings for merged pull requests, GitHub-attributed commits, and Git history + ([#11356](https://github.com/diegosouzapw/OmniRoute/pull/11356)). +- **docs(openapi):** document the conditionally management-authenticated, same-origin `POST /api/openapi/try` proxy contract and restore the release branch's operation-coverage ratchet ([#11363](https://github.com/diegosouzapw/OmniRoute/pull/11363)) +- **fix(video-bridge):** make opt-in segment-aware sampling use one bounded structural FFmpeg pass (scene, freeze, blur, exposure, and SI/TI), preserve long trailing segments, fail open to uniform sampling, and add real-media structural-oracle, overhead, post-dedup caption-call, and false-positive evidence while holding unconfigured model quality and gain-versus-cost claims ([#11381](https://github.com/diegosouzapw/OmniRoute/pull/11381)). +- **docs:** add an embeddings client runbook with live-verified working/broken model ids and Hindsight 0.9.1 / Memorix 1.6.0 notes — thanks @RaviTharuma +- **chore(ci):** ignore ad-hoc `BOT_TOKEN`/`BOT_URL` in env-doc-sync (scripts/ad-hoc mesh helpers, not runtime config) +- **test(kimi):** the Kimi background health sweep no longer draws its refresh window inside the assertion. `checkKimiWebConnectionIfNeeded` spreads the refresh over `[60, 240)` seconds before expiry so a fleet of connections does not stampede the token endpoint, and the test used a token expiring in 90 seconds and asserted that a refresh happened — which is true only when the draw lands at 90 or above, i.e. 150 of the 180 possible values. Measured: the test fails 1 run in 6 (16.7% by construction; 4 of 20 local runs), and it is what the Node 26 nightly hit and reported as a Node-compat break (#11361). The spread is now `defaultKimiRefreshJitterSec()` and the window is injectable as `jitterSecFn`, so the test decides it instead of rolling for it; production behaviour is unchanged. Cases were added for a token outside the window and for the default spread's range. +- chore(test): regenerate the provider/translate-path golden snapshot to reflect freebuff (#10531), fixing a base-red left by that merge (freebuff/freeinference key ordering only, no value changes). +- **chore(release):** resync the v3.8.50 provider and CLI catalogs, register the existing ChatCore mutation-coverage test, and document the local ZCode handshake identifier so the release quality gates reflect the current tree without changing ratchet baselines. +- **fix(ci):** route `open-sse/handlers/imageGeneration/providers/geminiWeb.ts`'s b64_json + download-failure message through `sanitizeErrorMessage()` instead of embedding a raw + `err.message`, clearing the `check:error-helper` base-red on `release/v3.8.50` (#9985). +- **fix(ci):** drain three more base-reds on `release/v3.8.50` (#9985). ESLint was reporting + 219 errors locally (vs. 25 in the last CI run) — all from `react-hooks/set-state-in-effect`, + `react-hooks/preserve-manual-memoization`, `react-hooks/immutability`, + `react-hooks/static-components`, `react-hooks/refs` and `react-hooks/purity`, six React + Compiler lint rules that `eslint-plugin-react-hooks` v7 turns on by default and that were + never frozen in `config/quality/eslint-suppressions.json` after the dependency bump. Froze + the pre-existing violations for those six rules via ESLint's native + `--suppress-rule`/`--suppressions-location` mechanism (the same pattern already used for + `@next/next/no-location-assign-relative-destination`) — no application code changed, no rule + disabled, only genuinely-new violations stay blocking. `check:dead-code` was at 418 against a + 415 baseline: removed the unused `src/lib/quota/providerCapabilities.ts` file and the unused + `ProviderQuotaMonitor` interface in `providerQuotaTelemetry.ts` (both dead since PR #10148, + 2026-08-18, confirmed via `grep`/knip cross-reference), landing at 416; the residual +1 could + not be attributed to a single recent commit after checking every dead-list entry touched + since the 2026-08-14 baseline measurement, so it is rebaselined with the investigation + recorded in `quality-baseline.json`. `tests/unit/autoCombo/tieredRotation.test.ts`'s + "rotates across all 43 Cerebras connection IDs" case was hitting vitest's 5000ms default + timeout on a 200-iteration synchronous `selectProvider()` loop under shared-devbox + contention (load average 40-60+ observed) — widened its explicit timeout to 20000ms; the + assertion itself is unchanged. +- **fix(tests):** drain two base-reds on the release branch — `auto/glm` now expects the Cloudflare AI Playground backend (its registry advertises `zai-org/glm-5.2` and `zai-org/glm-4.7-flash`, so it belongs in the family pool by the same rule already documented for `auggie`, `devin-cli-agentic` and `zcode`), and the ESLint gate is green again after the GitLab executor test dropped its five `as any` casts for a declared response shape and the CLI OAuth suppression count caught up with the two casts #10491 added. +- **fix(tests):** realign the two `stream-utils` passthrough cases that still asserted the pre-#10017 SSE framing — the event-boundary case declares the OpenAI Responses client format it actually exercises, and the metadata case now pins that surviving lines stay inside one event instead of expecting the `:`/`id:` control lines that #10473 stopped forwarding to every client format. +- **fix(tests):** drain several base-reds on `release/v3.8.50` (#9985) that were all instances + of the same pattern — a legitimate product change landed without updating the test that + asserted the old behavior: `tests/unit/glm-provider-model-import-route.test.ts` (12 tests) + and `tests/unit/model-sync-route.test.ts` (2 tests) predate #10603's "upstream model sync is + opt-in and manual overrides are preserved" change; `tests/unit/antigravity-model-aliases.test.ts` + predated #10537 retiring the collapsed `gemini-3.7-flash` alias in favor of its three tiered + ids. Also fixes a real data drift in `open-sse/config/freeModelCatalog.data.ts` (the `qwen-web` + free-catalog entry still pointed at the retired `qwen3.8-max-preview` id instead of the + current `qwen3.8-max`), corrects the zh-TW `providers.autoFetchModelsTooltip` string to the + glossary-canonical 快取 instead of 緩存, and removes an unused default export from + `src/lib/oauth/providers/zed-hosted.ts` (the named export already covers every consumer) to + shave one symbol off the `check:dead-code` ratchet regression. +- **chore(release):** synchronize migration-count documentation and document the opt-in `PROXY_LOG_INCLUDE_IPS` logging flag so the v3.8.50 quality gates match the release tree. +- fix(i18n): translate the 14 `providers.harImport*` keys into Vietnamese (parity gap left by #11069) ### 🙌 Contributors diff --git a/changelog.d/features/10039-combo-lane-awareness-wave-2.md b/changelog.d/features/10039-combo-lane-awareness-wave-2.md deleted file mode 100644 index 7c8cba55ba..0000000000 --- a/changelog.d/features/10039-combo-lane-awareness-wave-2.md +++ /dev/null @@ -1,2 +0,0 @@ -- **feat(admission):** add lane-aware admission probes for combo/fusion/chaos fan-out (fail-open, queueing disabled), an env-wins `OMNIROUTE_CHAT_VIRTUAL_LANES` activation flag applied at boot, and adaptive-lane visibility in the `omniroute_get_health` MCP tool (related to #9654) -- **docs(mcp):** complete the MCP server README tool reference so the `schemas/` catalog is fully covered (agent-skills, oneproxy, web, tool-search, combo/routing, pricing and DB-health tools were previously only discoverable via `omniroute_tool_search`) diff --git a/changelog.d/features/10057-docker-aware-auto-config.md b/changelog.d/features/10057-docker-aware-auto-config.md deleted file mode 100644 index d8718c5801..0000000000 --- a/changelog.d/features/10057-docker-aware-auto-config.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(cli):** container-aware auto-config — `setup-*`, `omniroute configure`, `omniroute config set` and the CLI-tool config APIs now refuse to write into a containerised OmniRoute's ephemeral home (CLI exits `2`, API returns `422` with `containerEphemeralTarget`) and point at the host-CLI or bind-mount setup instead; `--allow-container-write` / `OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE=true` opt back in. Also fixes `CLI_CONFIG_HOME` so the Compose `host` profile's `/host-home` bind mounts are honoured instead of silently falling back to the container home. (#10057) diff --git a/changelog.d/features/10273-dashboard-embed-csp.md b/changelog.d/features/10273-dashboard-embed-csp.md deleted file mode 100644 index 8627e0ddbe..0000000000 --- a/changelog.d/features/10273-dashboard-embed-csp.md +++ /dev/null @@ -1 +0,0 @@ -- feat(dashboard): opt-in `DASHBOARD_ALLOW_EMBED=vscode` relaxes CSP `frame-ancestors` to `'self' vscode-webview:` and drops `X-Frame-Options` for HTML pages only, so the dashboard renders inside the VS Code Simple Browser (OmniCopilot). Default posture unchanged — API routes stay unframable (#10273) diff --git a/changelog.d/features/10303-healthz-event-loop-lag.md b/changelog.d/features/10303-healthz-event-loop-lag.md deleted file mode 100644 index 991c123021..0000000000 --- a/changelog.d/features/10303-healthz-event-loop-lag.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(resilience):** warn when `/healthz` is served under event-loop lag ≥200ms so a slow 200 is visible as sick, not healthy ([#10303](https://github.com/diegosouzapw/OmniRoute/issues/10303)) diff --git a/changelog.d/features/10316-livez-endpoint.md b/changelog.d/features/10316-livez-endpoint.md deleted file mode 100644 index 01409d7b48..0000000000 --- a/changelog.d/features/10316-livez-endpoint.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(docker):** add `GET`/`HEAD` `/livez` as a process-alive probe, distinct from `/healthz` readiness ([#10316](https://github.com/diegosouzapw/OmniRoute/issues/10316)) diff --git a/changelog.d/features/10389-cloudflare-playground.md b/changelog.d/features/10389-cloudflare-playground.md deleted file mode 100644 index fb6bd80c0a..0000000000 --- a/changelog.d/features/10389-cloudflare-playground.md +++ /dev/null @@ -1 +0,0 @@ -- feat(providers): add **Cloudflare AI Playground** as a No Auth provider (`cloudflare-playground`, alias `cfp`) — free anonymous chat over the reverse-engineered `cf_agent` WebSocket protocol (PartySocket transport, no account/API key/cookies) with GLM 5.2, Kimi K2.7 Code, DeepSeek V4 Pro, gpt-oss-120B, Llama 3.3 70B, Qwen2.5 Coder 32B and 14 more curated models. The executor drives a headless Chromium via Playwright (the WS upgrade is TLS-fingerprint-gated), translates the `cf_agent` frame stream into OpenAI SSE, and surfaces upstream rate limits (3021) as HTTP 429. Fixes #10389 diff --git a/changelog.d/features/10542-aihorde-optional-key-image-catalog.md b/changelog.d/features/10542-aihorde-optional-key-image-catalog.md deleted file mode 100644 index 4a8f67b766..0000000000 --- a/changelog.d/features/10542-aihorde-optional-key-image-catalog.md +++ /dev/null @@ -1,2 +0,0 @@ -- **feat(providers):** AI Horde accepts an optional registered API key and advertises only live image models that currently have workers ([#10542](https://github.com/diegosouzapw/OmniRoute/pull/10542)) -- **fix(providers):** AI Horde Check validates keys via `/v2/find_user` instead of the unauthenticated OpenAI models list ([#10542](https://github.com/diegosouzapw/OmniRoute/pull/10542)) diff --git a/changelog.d/features/10556-elevenlabs-native-routes.md b/changelog.d/features/10556-elevenlabs-native-routes.md deleted file mode 100644 index 3fcb68d0aa..0000000000 --- a/changelog.d/features/10556-elevenlabs-native-routes.md +++ /dev/null @@ -1 +0,0 @@ -- **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). diff --git a/changelog.d/features/10581-jina-complete-provider.md b/changelog.d/features/10581-jina-complete-provider.md deleted file mode 100644 index d4fc0424a3..0000000000 --- a/changelog.d/features/10581-jina-complete-provider.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** complete Jina AI as one credential pool — dashboard `jina-ai` / `jina-reader` share a token, `JINA_AI_API_KEY` is a real fallback, Test probes `GET https://api.jina.ai/v1/models` (embeddings fallback hits `jina-embeddings-v5-omni-small`), embed/rerank logs keep `connection_id`, catalog adds `jina-reranker-v3.5`, Omni v5 multimodal `{text}`/`{image}`/`{content}` docs pass through intact, and OmniRoute proxies classify / segment / `jina-search` (`s.jina.ai`). Reader stays a separate `r.jina.ai` card with an explicit label. Gemini Embedding 2 (`gemini/gemini-embedding-2`, alias `google/gemini-embedding-2`) uses dashboard `gemini` keys (or `GEMINI_API_KEY` / `GOOGLE_API_KEY` only when none exist), forwards native multimodal parts, and maps N OpenAI `input` items to N `:batchEmbedContents` vectors instead of one aggregated `:embedContent`. ([#10581](https://github.com/diegosouzapw/OmniRoute/pull/10581)) diff --git a/changelog.d/features/10587-ogg-speech-alias.md b/changelog.d/features/10587-ogg-speech-alias.md deleted file mode 100644 index 118e2a7b48..0000000000 --- a/changelog.d/features/10587-ogg-speech-alias.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** accept `response_format=ogg` on `/v1/audio/speech` as an alias for the existing Opus/Ogg encoder ([#10587](https://github.com/diegosouzapw/OmniRoute/issues/10587)) diff --git a/changelog.d/features/10590-google-ai-studio-tts.md b/changelog.d/features/10590-google-ai-studio-tts.md deleted file mode 100644 index 9fcf931919..0000000000 --- a/changelog.d/features/10590-google-ai-studio-tts.md +++ /dev/null @@ -1 +0,0 @@ -- Added Google AI Studio Gemini batch text-to-speech support through `POST /v1/audio/speech`. diff --git a/changelog.d/features/10617-auto-disable-banned-scope.md b/changelog.d/features/10617-auto-disable-banned-scope.md deleted file mode 100644 index e1fc1705a8..0000000000 --- a/changelog.d/features/10617-auto-disable-banned-scope.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(settings):** add `autoDisableBannedScope` so permanent-ban auto-disable can target subscription/OAuth accounts only, leaving prepaid API keys in the routing pool ([#10617](https://github.com/diegosouzapw/OmniRoute/pull/10617)) diff --git a/changelog.d/features/10662-systemd-notify.md b/changelog.d/features/10662-systemd-notify.md deleted file mode 100644 index 5a02e7df25..0000000000 --- a/changelog.d/features/10662-systemd-notify.md +++ /dev/null @@ -1 +0,0 @@ -- feat(server): emit systemd sd_notify READY/WATCHDOG/STOPPING (generated unit becomes Type=notify with WatchdogSec=180) so a frozen server process is killed and restarted by systemd instead of lingering undetected diff --git a/changelog.d/features/10668-newapi-gateway-protocols.md b/changelog.d/features/10668-newapi-gateway-protocols.md deleted file mode 100644 index 1ec6e5f0b7..0000000000 --- a/changelog.d/features/10668-newapi-gateway-protocols.md +++ /dev/null @@ -1,2 +0,0 @@ -- **feat(providers):** add the TabiToken NewAPI gateway (`tabitoken`) and teach the existing HCNSec entry (`hcnsec`) the three further protocols it actually serves. TabiToken leaves the NewAPI pricing endpoint public, so its catalog is read from the host rather than guessed: four Claude models, each reporting the Anthropic and OpenAI protocols. HCNSec shipped OpenAI-only; probing the host showed `/v1/messages`, `/v1/responses` and the Gemini `/v1beta` path all reach its token layer, so each is now declared as an alternate format — with its default format, base URL, auth scheme and regional catalog classification untouched. ([#10668](https://github.com/diegosouzapw/OmniRoute/pull/10668)) — thanks @yawar-aquil -- **feat(sse):** allow an alternate protocol to build its own upstream URL. `AlternateFormat` gained an optional `urlBuilder`, because the Gemini protocol carries the model inside the path (`{base}/{model}:generateContent`) and the existing `chatPath`/`urlSuffix` fields are constants that cannot express it. The route builder is extracted as `buildGeminiGenerateContentUrl` and shared with the native `gemini` provider so the two consumers cannot drift on the `?alt=sse` streaming suffix. ([#10668](https://github.com/diegosouzapw/OmniRoute/pull/10668)) — thanks @yawar-aquil diff --git a/changelog.d/features/10670-call-logs-error-type.md b/changelog.d/features/10670-call-logs-error-type.md deleted file mode 100644 index 1ffd94bd22..0000000000 --- a/changelog.d/features/10670-call-logs-error-type.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(call_logs):** persist the per-call error family in `call_logs.error_type` and expose a failure breakdown (`errorBreakdown`) in the usage analytics endpoint, reusing the existing production classifier ([#10670](https://github.com/diegosouzapw/OmniRoute/issues/10670)) diff --git a/changelog.d/features/10677-egress-sharing-summary.md b/changelog.d/features/10677-egress-sharing-summary.md deleted file mode 100644 index 9e1f723a0d..0000000000 --- a/changelog.d/features/10677-egress-sharing-summary.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(proxy):** the proxy-health sweep and `GET /api/settings/proxies/egress` now report an anonymous summary of egress-IP sharing — how many rotation groups share an egress IP and the largest number of accounts behind one IP — computed from persisted `proxy_logs` over a 24h window. No IPs and no account identities by default; `PROXY_LOG_INCLUDE_IPS=true` restores raw details. ([#10677](https://github.com/diegosouzapw/OmniRoute/issues/10677)) diff --git a/changelog.d/features/10697-vscode-copilot-guide.md b/changelog.d/features/10697-vscode-copilot-guide.md deleted file mode 100644 index ec788c7183..0000000000 --- a/changelog.d/features/10697-vscode-copilot-guide.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(guides):** OmniRoute now serves VS Code's **native Copilot Chat model picker** through the [OmniCopilot](https://github.com/diegosouzapw/OmniCopilot) extension ([Marketplace](https://marketplace.visualstudio.com/items?itemName=diegosouzapw.omnicopilot) · [Open VSX](https://open-vsx.org/extension/diegosouzapw/omnicopilot) — Cursor, Windsurf, VSCodium, Theia…) — no Copilot subscription needed since VS Code 1.122. New [`docs/guides/VSCODE-COPILOT.md`](docs/guides/VSCODE-COPILOT.md) covers setup, how the picker collapses the `dual`-prefix catalog via `GET /v1/models?prefix=alias`, and the **build-time** `DASHBOARD_ALLOW_EMBED=vscode` flag that renders the dashboard in an editor tab ([#10697](https://github.com/diegosouzapw/OmniRoute/pull/10697)) diff --git a/changelog.d/features/10701-dockerfile-dashboard-embed-arg.md b/changelog.d/features/10701-dockerfile-dashboard-embed-arg.md deleted file mode 100644 index 552a873268..0000000000 --- a/changelog.d/features/10701-dockerfile-dashboard-embed-arg.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(docker):** `DASHBOARD_ALLOW_EMBED` is now a Docker build argument — `docker build --build-arg DASHBOARD_ALLOW_EMBED=vscode` produces an image whose dashboard renders inside the VS Code Simple Browser (OmniCopilot's `dashboardOpen: "editor"`). Previously the flag was only reachable from a source build: Docker silently drops a `--build-arg` with no matching `ARG`, so the operator got the default image and no error. Builder-stage only and empty by default — the runtime stages deliberately do not carry it, and the unframable default posture is unchanged ([#10701](https://github.com/diegosouzapw/OmniRoute/pull/10701)) diff --git a/changelog.d/features/10729-cursor-api-key-and-cli-passthrough.md b/changelog.d/features/10729-cursor-api-key-and-cli-passthrough.md deleted file mode 100644 index 96094ffff1..0000000000 --- a/changelog.d/features/10729-cursor-api-key-and-cli-passthrough.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** new `cursor-api` provider (card "Cursor API", alias `cua`): connect a Cursor user API key (`crsr_…`) and route `cursor-api/` through the existing Cursor agent executor (the key is exchanged for a 1h session token and cached), plus a `/api/cursor-cli/*` passthrough so the Cursor CLI itself runs through OmniRoute (`CURSOR_API_ENDPOINT=http:///api/cursor-cli`, `CURSOR_API_KEY=`) with every RPC attributed and logged. The IDE `cursor` provider is unchanged. (#10729) diff --git a/changelog.d/features/10771-health-root-endpoint.md b/changelog.d/features/10771-health-root-endpoint.md deleted file mode 100644 index a367bbce78..0000000000 --- a/changelog.d/features/10771-health-root-endpoint.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(api):** `GET /api/health` now answers `{ status, timestamp }` without a key. Until now the path had no route, so the management-auth boundary answered first with a 401 — indistinguishable from a wrong key or an unknown route, which left Docker HEALTHCHECKs and Kubernetes probes unable to tell "down" from "misconfigured". Kept deliberately minimal: version, uptime and memory stay behind the authenticated `/api/monitoring/health` ([#PRNUM](https://github.com/diegosouzapw/OmniRoute/pull/10771)). diff --git a/changelog.d/features/10783-task-routing-configurable-patterns.md b/changelog.d/features/10783-task-routing-configurable-patterns.md deleted file mode 100644 index e5c37c390a..0000000000 --- a/changelog.d/features/10783-task-routing-configurable-patterns.md +++ /dev/null @@ -1 +0,0 @@ -- feat(routing): make Task-Aware Smart Routing's detection patterns operator-configurable via `settings.taskRouting.patternOverrides` (`PUT /api/settings/task-routing`) — the built-in patterns are English-only, so a non-English dashboard had no recourse short of turning detection off entirely; an override now replaces the pattern list for one task type without touching the rest (#10783) diff --git a/changelog.d/features/10869-combo-patch-verb.md b/changelog.d/features/10869-combo-patch-verb.md deleted file mode 100644 index f11893d95c..0000000000 --- a/changelog.d/features/10869-combo-patch-verb.md +++ /dev/null @@ -1 +0,0 @@ -- feat(api): accept PATCH on /api/combos/[id], the verb the OpenAPI spec already documents (#10869) diff --git a/changelog.d/features/10896-glm-5.3.md b/changelog.d/features/10896-glm-5.3.md deleted file mode 100644 index 0edfc4a55b..0000000000 --- a/changelog.d/features/10896-glm-5.3.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(sse):** add GLM-5.3 support (`glm-5.3`, `glm-5.3-high`, `glm-5.3-low`) across the z.ai first-party providers, mapping the upstream `reasoning_effort` request parameter to the existing 5.2 tier UX ([#10896](https://github.com/diegosouzapw/OmniRoute/pull/10896)) — thanks @phuongddx diff --git a/changelog.d/features/10897-home-recent-requests.md b/changelog.d/features/10897-home-recent-requests.md deleted file mode 100644 index fd6bcc9abe..0000000000 --- a/changelog.d/features/10897-home-recent-requests.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(home):** add a live **Recent Requests** panel beside the home Provider Topology (polls `GET /api/usage/call-logs?excludeTests=1` every ~3s, gated by the topology appearance toggle + page visibility). `excludeTests` is now an allowlist of real provider inference (`/v1/%` or `/api/v1/%`), applied before `LIMIT`, so connection-test/model-sync/management rows can never leak into the feed ([#10897](https://github.com/diegosouzapw/OmniRoute/pull/10897), extracted from [#8450](https://github.com/diegosouzapw/OmniRoute/pull/8450)) — thanks @nguyenha935 diff --git a/changelog.d/features/10909-free-provider-rankings-reliability.md b/changelog.d/features/10909-free-provider-rankings-reliability.md deleted file mode 100644 index e5377885ef..0000000000 --- a/changelog.d/features/10909-free-provider-rankings-reliability.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(rankings):** free provider rankings now expose a `reliability` field (raw `testStatus`/`rateLimitedUntil` per connection plus a `healthy`/`degraded`/`down` state, reusing the `ProviderHealthState` vocabulary of the provider health matrix) when the configured/available filters are active — derived from already-loaded data, without touching the ranking order ([#10909](https://github.com/diegosouzapw/OmniRoute/pull/10909)) diff --git a/changelog.d/features/10920-egress-ip-lock.md b/changelog.d/features/10920-egress-ip-lock.md deleted file mode 100644 index af7308b62f..0000000000 --- a/changelog.d/features/10920-egress-ip-lock.md +++ /dev/null @@ -1,8 +0,0 @@ -- `feat(resilience)`: when an allowlisted provider (opencode family) answers - 429 classified `quota_exhausted` or `rate_limit_exceeded` and its free-tier - quota is bucketed by egress IP (#9611), every connection of that family - sharing the IP is cooled down together before the rotation tries them — one - guaranteed-failed upstream call per episode instead of N, on the combo path - as well. For the allowlisted family a 429 now cools the connection instead - of locking a single model. Exclusive allowlist, never terminal, best-effort - when the egress IP is unknown (#10920). diff --git a/changelog.d/features/10926-rankings-usage-reliability.md b/changelog.d/features/10926-rankings-usage-reliability.md deleted file mode 100644 index a79b92b4cf..0000000000 --- a/changelog.d/features/10926-rankings-usage-reliability.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(rankings):** free provider rankings can now report what each provider actually served — `reliability.usage` (requests, successes, success rate over a window) behind the opt-in `withUsage`/`usageRange` query parameters, so a provider that answers every call with an error is no longer described as healthy ([#10926](https://github.com/diegosouzapw/OmniRoute/pull/10926)) diff --git a/changelog.d/features/10987-logfare-free-provider.md b/changelog.d/features/10987-logfare-free-provider.md deleted file mode 100644 index 507a528411..0000000000 --- a/changelog.d/features/10987-logfare-free-provider.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** add Logfare as a free OpenAI-compatible provider — dashboard card with a Free badge and request-logging disclosure (every prompt/completion is logged for research; opt out at logfare.ai/consent), live model discovery from `https://logfare.ai/v1/models` (20 models, 11 chat-capable: kimi-k3, deepseek-v4-pro, glm-5.2, gpt-5.6-luna, minimax-m3…), full chat/streaming through the existing OpenAI-compatible path, the real Logfare logo on the card, and a listing in the free-tiers guide. ([#10987](https://github.com/diegosouzapw/OmniRoute/pull/10987)) diff --git a/changelog.d/features/11023-compression-worker-pool.md b/changelog.d/features/11023-compression-worker-pool.md deleted file mode 100644 index 4d9c1b9d60..0000000000 --- a/changelog.d/features/11023-compression-worker-pool.md +++ /dev/null @@ -1,3 +0,0 @@ -- 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. diff --git a/changelog.d/features/11104-operator-error-rules.md b/changelog.d/features/11104-operator-error-rules.md deleted file mode 100644 index f31e78c01f..0000000000 --- a/changelog.d/features/11104-operator-error-rules.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/features/11134-configurable-max-global-attempts.md b/changelog.d/features/11134-configurable-max-global-attempts.md deleted file mode 100644 index 2a5605061b..0000000000 --- a/changelog.d/features/11134-configurable-max-global-attempts.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/features/11190-usage-command-json.md b/changelog.d/features/11190-usage-command-json.md deleted file mode 100644 index d7655f04c5..0000000000 --- a/changelog.d/features/11190-usage-command-json.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/features/11192-usage-command-providers-array.md b/changelog.d/features/11192-usage-command-providers-array.md deleted file mode 100644 index b7ef421109..0000000000 --- a/changelog.d/features/11192-usage-command-providers-array.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/features/11251-connection-max-wait-ms-override.md b/changelog.d/features/11251-connection-max-wait-ms-override.md deleted file mode 100644 index 25ac42dd98..0000000000 --- a/changelog.d/features/11251-connection-max-wait-ms-override.md +++ /dev/null @@ -1 +0,0 @@ -- **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) diff --git a/changelog.d/features/11282-first-run-readiness-card.md b/changelog.d/features/11282-first-run-readiness-card.md deleted file mode 100644 index e2899a54e5..0000000000 --- a/changelog.d/features/11282-first-run-readiness-card.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/features/11283-traffic-inspector-purpose-header.md b/changelog.d/features/11283-traffic-inspector-purpose-header.md deleted file mode 100644 index 4faaf5bc57..0000000000 --- a/changelog.d/features/11283-traffic-inspector-purpose-header.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/features/11286-essentials-sidebar-preset.md b/changelog.d/features/11286-essentials-sidebar-preset.md deleted file mode 100644 index f05152001a..0000000000 --- a/changelog.d/features/11286-essentials-sidebar-preset.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/features/11369-video-bridge-drilldown-isolation.md b/changelog.d/features/11369-video-bridge-drilldown-isolation.md deleted file mode 100644 index b0b499304d..0000000000 --- a/changelog.d/features/11369-video-bridge-drilldown-isolation.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(video bridge):** harden the optional drill-down cache substrate with exact-path broker policy, canonical principal/session/media isolation, independent retained-byte quotas, cancellation-safe commits, rejection of excess or non-canonical Base64 padding and non-JPEG/truncated media, warning-sensitive full JPEG canonicalization that strips trailing polyglot bytes, server-derived dimensions, and auditable derivation metadata; production tenant binding and multi-resolution selection remain follow-up work ([#11369](https://github.com/diegosouzapw/OmniRoute/pull/11369)) diff --git a/changelog.d/features/11383-video-bridge-focused-mode.md b/changelog.d/features/11383-video-bridge-focused-mode.md deleted file mode 100644 index a5d06efb00..0000000000 --- a/changelog.d/features/11383-video-bridge-focused-mode.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(video):** add an opt-in focused analysis mode that safely uses a normalized, 500-code-point latest-user hint for task-aware frame captions while preserving full-mode prompts, temporal-window isolation, and cache identity without storing raw task text ([#11383](https://github.com/diegosouzapw/OmniRoute/pull/11383)). diff --git a/changelog.d/features/6342-cliproxy-account-health.md b/changelog.d/features/6342-cliproxy-account-health.md deleted file mode 100644 index 69b57b41fd..0000000000 --- a/changelog.d/features/6342-cliproxy-account-health.md +++ /dev/null @@ -1 +0,0 @@ -- feat(services): show sanitized CLIProxyAPI account health from its authenticated management API without exposing credentials, file paths, or raw account metadata (#6342) diff --git a/changelog.d/features/8443-credential-health-per-connection-interval.md b/changelog.d/features/8443-credential-health-per-connection-interval.md deleted file mode 100644 index 1fd1d3e5a2..0000000000 --- a/changelog.d/features/8443-credential-health-per-connection-interval.md +++ /dev/null @@ -1,2 +0,0 @@ -- **feat(credential-health):** pace the credential health sweep per connection via `provider_connections.healthCheckInterval` (minutes, 0 = never), with `CREDENTIAL_HEALTH_CHECK_INTERVAL` as the global default ([#8443](https://github.com/diegosouzapw/OmniRoute/issues/8443)) -- **behavior change:** `healthCheckInterval` is a shared column — it paces both the OAuth token refresh and the credential health sweep, and `0` disables both. The connection editor defaults it to 60, so configured OAuth connections are now credential-checked at 60min instead of the previous ~10min (aligned with the probe-volume goal of #8443) diff --git a/changelog.d/features/9085-poolside-laguna-model-ids.md b/changelog.d/features/9085-poolside-laguna-model-ids.md deleted file mode 100644 index ed4c0229db..0000000000 --- a/changelog.d/features/9085-poolside-laguna-model-ids.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** publish Poolside's Laguna Preview catalog statically — `poolside/laguna-xs-2.1` and `poolside/laguna-s-2.1` (262144 context, 32768 max completion, tools + reasoning, text-only), so the models are routable and visible before a key is configured instead of only after live discovery. Pins the catalog form of the XS id against the `laguna-xs.2` variant carried by third-party listings. ([#9085](https://github.com/diegosouzapw/OmniRoute/issues/9085)) diff --git a/changelog.d/features/9760-video-bridge.md b/changelog.d/features/9760-video-bridge.md deleted file mode 100644 index cc2ceca74a..0000000000 --- a/changelog.d/features/9760-video-bridge.md +++ /dev/null @@ -1 +0,0 @@ -- feat(modality-bridge): bridge Chat and Responses video parts through a strict trusted-loopback, quota-bounded FFmpeg broker; enforce HTTPS redirects/SSRF plus format, protocol, stream, pixel, frame, 50 MiB broker/remote, 36 MiB inline, and 120-second limits; propagate caller aborts; preserve the actual successful fallback model through cache/meta/headers; expose sampled latency and honest success telemetry; and ship the localized Video settings UI (#9760) diff --git a/changelog.d/features/9830-radar-local-model-state.md b/changelog.d/features/9830-radar-local-model-state.md deleted file mode 100644 index a6df34c7e7..0000000000 --- a/changelog.d/features/9830-radar-local-model-state.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(radar):** Persist local model display-name/enabled overrides and hide/restore tombstones, with authenticated catalog controls and feed safety precedence ([#9830](https://github.com/diegosouzapw/OmniRoute/pull/9830)) diff --git a/changelog.d/features/9836-radar-guided-combos.md b/changelog.d/features/9836-radar-guided-combos.md deleted file mode 100644 index c813289b35..0000000000 --- a/changelog.d/features/9836-radar-guided-combos.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(radar):** add curated-family combo suggestions, a guided combo page, and the read-only Radar MCP catalog tool ([#9836](https://github.com/diegosouzapw/OmniRoute/pull/9836)) diff --git a/changelog.d/features/9912-radar-supporter-offers.md b/changelog.d/features/9912-radar-supporter-offers.md deleted file mode 100644 index a394c737e9..0000000000 --- a/changelog.d/features/9912-radar-supporter-offers.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(radar):** add a signed live offers feed and supporter offers dashboard ([#9912](https://github.com/diegosouzapw/OmniRoute/pull/9912)) diff --git a/changelog.d/features/9923-radar-intel.md b/changelog.d/features/9923-radar-intel.md deleted file mode 100644 index 033b3fc4b3..0000000000 --- a/changelog.d/features/9923-radar-intel.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(radar):** add signed Intel insights, supporter recognition, and local Radar CLI commands ([#9923](https://github.com/diegosouzapw/OmniRoute/pull/9923)) diff --git a/changelog.d/features/9926-radar-launch-news.md b/changelog.d/features/9926-radar-launch-news.md deleted file mode 100644 index 9ec56bebd0..0000000000 --- a/changelog.d/features/9926-radar-launch-news.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(radar):** add a localized public news feed and dismissible dashboard launch banner, with the Radar announcement staged inactive for a separately authorized launch ([#9926](https://github.com/diegosouzapw/OmniRoute/pull/9926)) diff --git a/changelog.d/features/command-code-reasoning-efforts.md b/changelog.d/features/command-code-reasoning-efforts.md deleted file mode 100644 index 3e9b172204..0000000000 --- a/changelog.d/features/command-code-reasoning-efforts.md +++ /dev/null @@ -1 +0,0 @@ -- feat(command-code): advertise low/medium/high/xhigh/max reasoning-effort suffixes for reasoning-capable models in the catalog and Combo Builder, with request-time resolution to reasoning_effort diff --git a/changelog.d/features/crofai-reasoning-efforts.md b/changelog.d/features/crofai-reasoning-efforts.md deleted file mode 100644 index 6a84017aba..0000000000 --- a/changelog.d/features/crofai-reasoning-efforts.md +++ /dev/null @@ -1 +0,0 @@ -- feat(crof): advertise reasoning-effort tiers (none/low/medium/high/max) for live-discovered and seed models, so the catalog, Playground, and Combo Builder surface - aliases and requests resolve max upstream diff --git a/changelog.d/features/cursor-agent-image-provider.md b/changelog.d/features/cursor-agent-image-provider.md deleted file mode 100644 index 84646dc44e..0000000000 --- a/changelog.d/features/cursor-agent-image-provider.md +++ /dev/null @@ -1 +0,0 @@ -- feat(sse): add Cursor plan image generation via Agent CLI (`IMAGE_PROVIDERS.cursor`, format `cursor-agent-image`), reusing the chat Cursor OAuth connection diff --git a/changelog.d/features/disable-context-window-checks.md b/changelog.d/features/disable-context-window-checks.md deleted file mode 100644 index 1cdd3cc0a8..0000000000 --- a/changelog.d/features/disable-context-window-checks.md +++ /dev/null @@ -1 +0,0 @@ -- feat(routing): add the default-off `DISABLE_CONTEXT_WINDOW_CHECKS` feature flag to let operators bypass OmniRoute's local context-window and max-input-token check for direct single-model requests, leaving upstream limits, prompt compression, and output-token caps intact. diff --git a/changelog.d/features/effort-tiers-loop-learned-sets.md b/changelog.d/features/effort-tiers-loop-learned-sets.md deleted file mode 100644 index 29b5b10ec6..0000000000 --- a/changelog.d/features/effort-tiers-loop-learned-sets.md +++ /dev/null @@ -1 +0,0 @@ -- **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 `-` 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) diff --git a/changelog.d/features/kimi-coding-extra-usage.md b/changelog.d/features/kimi-coding-extra-usage.md deleted file mode 100644 index 766ec1020c..0000000000 --- a/changelog.d/features/kimi-coding-extra-usage.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(usage):** show Kimi Coding's fixed-order Code 5-hour/7-day quota windows plus Extra Usage status, balance, monthly spend/limit, and the official Additional Credits link on Dashboard → Quota cards. diff --git a/changelog.d/features/m365-copilot-tool-calls.md b/changelog.d/features/m365-copilot-tool-calls.md deleted file mode 100644 index bfafe08033..0000000000 --- a/changelog.d/features/m365-copilot-tool-calls.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** copilot-m365-web now supports OpenAI tool calling — a router planning turn asks the substrate model (as a tool-selection assistant emitting `CALL_TOOL: name({...})` / `NO_TOOL_NEEDED` text, which bypasses its plugin-registry refusal) and validated decisions surface as `tool_calls` with `finish_reason: "tool_calls"` in both stream and non-stream modes; also flattens the full message history (assistant `tool_calls` + compacted tool results) so multi-turn agent loops keep context, replies to SignalR `type:6` keepalives, surfaces `type:3` error frames instead of a silent empty `stop`, and suppresses `writeAtCursor` text from tool-progress frames diff --git a/changelog.d/features/multimodal-embeddings-alias.md b/changelog.d/features/multimodal-embeddings-alias.md deleted file mode 100644 index b69c53ecb5..0000000000 --- a/changelog.d/features/multimodal-embeddings-alias.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(api):** add `GET`/`POST` `/v1/multimodal-embeddings` as an alias of `/v1/embeddings` so Jina-compatible clients do not receive HTTP 404 `unknown_route` — thanks @RaviTharuma diff --git a/changelog.d/features/opencode-go-muse-spark-efforts.md b/changelog.d/features/opencode-go-muse-spark-efforts.md deleted file mode 100644 index 25da8482a9..0000000000 --- a/changelog.d/features/opencode-go-muse-spark-efforts.md +++ /dev/null @@ -1 +0,0 @@ -- feat(opencode-go): expose Muse Spark 1.2 Contributor reasoning-effort aliases (minimal/low/medium/high/xhigh) in the Combo Builder diff --git a/changelog.d/features/per-connection-upstream-timeout.md b/changelog.d/features/per-connection-upstream-timeout.md deleted file mode 100644 index a5987ed485..0000000000 --- a/changelog.d/features/per-connection-upstream-timeout.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** restore the operator-owned upstream timeout tier per connection via `providerSpecificData.timeoutMs` (preempts the maintainer-only model/provider registry tiers and the global `FETCH_TIMEOUT_MS`), and make the combo per-target timeout ceiling follow the selected connection \ No newline at end of file diff --git a/changelog.d/features/unreleased-detached-cli-tray.md b/changelog.d/features/unreleased-detached-cli-tray.md deleted file mode 100644 index e556a57dc0..0000000000 --- a/changelog.d/features/unreleased-detached-cli-tray.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(cli):** run `omniroute serve --tray` as a detached desktop process after server and tray readiness, with graphical login auto-start support. diff --git a/changelog.d/features/unreleased-exclusive-managed-session-leases.md b/changelog.d/features/unreleased-exclusive-managed-session-leases.md deleted file mode 100644 index 9db23724ef..0000000000 --- a/changelog.d/features/unreleased-exclusive-managed-session-leases.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(routing):** add client-, provider-, and model-neutral exclusive managed session connection leases with API-key-bound generation fencing, durable SQLite ownership, explicit allowlist policy, and bounded 429 capacity retry semantics. diff --git a/changelog.d/fixes/10017-sse-control-lines-leak-openai-clients.md b/changelog.d/fixes/10017-sse-control-lines-leak-openai-clients.md deleted file mode 100644 index 3c129442b4..0000000000 --- a/changelog.d/fixes/10017-sse-control-lines-leak-openai-clients.md +++ /dev/null @@ -1 +0,0 @@ -- **Passthrough streaming:** stop leaking upstream SSE control lines (`id:`/`event:`/`retry:`/`:` comments) to plain OpenAI Chat-Completions-format clients, while preserving `event:` framing for OpenAI Responses API and Claude Messages API passthrough ([#10017](https://github.com/diegosouzapw/OmniRoute/issues/10017)). diff --git a/changelog.d/fixes/10028-windows-instrumentation-hook.md b/changelog.d/fixes/10028-windows-instrumentation-hook.md deleted file mode 100644 index 9879e2f3f3..0000000000 --- a/changelog.d/fixes/10028-windows-instrumentation-hook.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): stop diagnosing every Next.js instrumentation-hook failure as the Android/Termux cache bug — only the Android "Unsupported platform: android" signal now triggers the Android hint, so a win32/desktop instrumentation error surfaces its real cause instead of a useless `mkdir -p ~/.cache` (#10028) \ No newline at end of file diff --git a/changelog.d/fixes/10060-build-sqlite-native-addon-guard.md b/changelog.d/fixes/10060-build-sqlite-native-addon-guard.md deleted file mode 100644 index b803a14cf8..0000000000 --- a/changelog.d/fixes/10060-build-sqlite-native-addon-guard.md +++ /dev/null @@ -1 +0,0 @@ -- **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. diff --git a/changelog.d/fixes/10071-g4f-space-anonymous-tier-proof-of-work.md b/changelog.d/fixes/10071-g4f-space-anonymous-tier-proof-of-work.md deleted file mode 100644 index 47f8de84fd..0000000000 --- a/changelog.d/fixes/10071-g4f-space-anonymous-tier-proof-of-work.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** the five g4f.space sub-providers (Groq, Gemini, Pollinations, Ollama, NVIDIA) no longer advertise a free tier — a keyless `POST /v1/chat/completions` now returns `402 insufficient_credits` behind a proof-of-work "cake" wall (re-verified live 2026-08-22), so `hasFree` is `false` and the notes point at `g4f.dev/members.html`. The gateway still works with a member key, so its registry wiring and `authType: "optional"` are unchanged ([#10071](https://github.com/diegosouzapw/OmniRoute/issues/10071)) — thanks @chirag127 diff --git a/changelog.d/fixes/10077-chatgpt-web-max-thinking-effort.md b/changelog.d/fixes/10077-chatgpt-web-max-thinking-effort.md deleted file mode 100644 index bf603f72d5..0000000000 --- a/changelog.d/fixes/10077-chatgpt-web-max-thinking-effort.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(chatgpt-web):** Preserve native `max` thinking effort through ChatGPT Web routing ([#10077](https://github.com/diegosouzapw/OmniRoute/pull/10077)) — thanks @zannen7 diff --git a/changelog.d/fixes/10078-agentrouter-quota-missing-dashboard.md b/changelog.d/fixes/10078-agentrouter-quota-missing-dashboard.md deleted file mode 100644 index b67fcc0f62..0000000000 --- a/changelog.d/fixes/10078-agentrouter-quota-missing-dashboard.md +++ /dev/null @@ -1,2 +0,0 @@ -- Fix: wire AgentRouter's existing console balance fetcher into the Dashboard Quota UI (visibility gate + provider-limits data path + background sync) so its wallet balance renders instead of falling back to "Usage API not implemented" (#10078) -- Fix: AgentRouter's dollar balance now renders as a currency-formatted "$X.XX" credits row in the Dashboard Quota UI instead of a bare percentage, and an exhausted wallet always shows exactly $0.00 (#10078) \ No newline at end of file diff --git a/changelog.d/fixes/10085-compatible-chat-credential-mismatch.md b/changelog.d/fixes/10085-compatible-chat-credential-mismatch.md deleted file mode 100644 index 773d4ed3cb..0000000000 --- a/changelog.d/fixes/10085-compatible-chat-credential-mismatch.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): bridge generic openai-compatible/anthropic-compatible provider type ids to their concrete uuid node id in credential lookup (#10085) diff --git a/changelog.d/fixes/10095-antigravity-multiaccount-quota-false-exhaustion.md b/changelog.d/fixes/10095-antigravity-multiaccount-quota-false-exhaustion.md deleted file mode 100644 index 579005e943..0000000000 --- a/changelog.d/fixes/10095-antigravity-multiaccount-quota-false-exhaustion.md +++ /dev/null @@ -1 +0,0 @@ -- fix(domain): stop treating an unreported Antigravity quota fraction (`fractionReported:false`) as 0% remaining in `quotaCache.ts`, which was falsely marking every fresh/newly-connected account as exhausted and blocking multi-account rotation (#10095) diff --git a/changelog.d/fixes/10096-kimi-coding-apikey-save.md b/changelog.d/fixes/10096-kimi-coding-apikey-save.md deleted file mode 100644 index 2b5f1bb8b6..0000000000 --- a/changelog.d/fixes/10096-kimi-coding-apikey-save.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): remap unified Kimi Code card API-key save to the admitted `kimi-coding-apikey` connection id, fixing 400 "Invalid provider" on Save (#10096) diff --git a/changelog.d/fixes/10104-antigravity-trailing-model-turn.md b/changelog.d/fixes/10104-antigravity-trailing-model-turn.md deleted file mode 100644 index 80af15279f..0000000000 --- a/changelog.d/fixes/10104-antigravity-trailing-model-turn.md +++ /dev/null @@ -1 +0,0 @@ -- fix(antigravity): strip trailing model turn for native Gemini requests too, not just Claude (#10104) diff --git a/changelog.d/fixes/10111-adaptive-admission-latency-collapse.md b/changelog.d/fixes/10111-adaptive-admission-latency-collapse.md deleted file mode 100644 index 1b806d53e6..0000000000 --- a/changelog.d/fixes/10111-adaptive-admission-latency-collapse.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(admission):** stop the adaptive latency-gradient collapse from permanently locking out ordinary requests — individually valid requests now make solo progress when the system is idle and normal pressure, and the collapsed limit actively recovers on sustained idle windows instead of being stuck; the critical-pressure fuse still wins over solo progress (#10111) \ No newline at end of file diff --git a/changelog.d/fixes/10119-claude-haiku-45-capability-flags.md b/changelog.d/fixes/10119-claude-haiku-45-capability-flags.md deleted file mode 100644 index 799486ffb0..0000000000 --- a/changelog.d/fixes/10119-claude-haiku-45-capability-flags.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): downgrade client-supplied `thinking:{type:"adaptive"}` to `enabled` and gate the `context-1m-2025-08-07` beta on model eligibility when a combo/fallback re-routes a request to a non-adaptive/non-1M model like claude-haiku-4-5 (avoids "adaptive thinking is not supported on this model" and "long context beta is not yet available" 400s, #10119) \ No newline at end of file diff --git a/changelog.d/fixes/10123-async-call-log-artifacts.md b/changelog.d/fixes/10123-async-call-log-artifacts.md deleted file mode 100644 index 60afcde1cc..0000000000 --- a/changelog.d/fixes/10123-async-call-log-artifacts.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(logging):** move call-log artifact serialization and filesystem writes to a bounded singleton worker to keep request handling responsive (#10123) diff --git a/changelog.d/fixes/10125-incremental-call-log-rotation.md b/changelog.d/fixes/10125-incremental-call-log-rotation.md deleted file mode 100644 index 50657fb19e..0000000000 --- a/changelog.d/fixes/10125-incremental-call-log-rotation.md +++ /dev/null @@ -1 +0,0 @@ -- **perf(logging):** bound each scheduled call-log rotation pass to incremental database and filesystem work (#10125) diff --git a/changelog.d/fixes/10127-early-sse-heartbeat.md b/changelog.d/fixes/10127-early-sse-heartbeat.md deleted file mode 100644 index 4ada9f43a4..0000000000 --- a/changelog.d/fixes/10127-early-sse-heartbeat.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(streaming):** start early SSE heartbeats when Responses or Messages requests opt into streaming through the request body (#10127) diff --git a/changelog.d/fixes/10136-combo-scoped-session-stickiness.md b/changelog.d/fixes/10136-combo-scoped-session-stickiness.md deleted file mode 100644 index 6cab4a2a7b..0000000000 --- a/changelog.d/fixes/10136-combo-scoped-session-stickiness.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(combo):** scope session-stickiness bindings to their owning Combo so identical first messages cannot carry a successful target into another priority chain and bypass its configured order (fixes #10136) diff --git a/changelog.d/fixes/10139-thinking-output-cap-provider-scope.md b/changelog.d/fixes/10139-thinking-output-cap-provider-scope.md deleted file mode 100644 index 6fc97e467a..0000000000 --- a/changelog.d/fixes/10139-thinking-output-cap-provider-scope.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** resolve the Claude thinking output cap with the routed provider so a provider-scoped-only `max_output_tokens` override is no longer invisible to `fitThinkingToMaxTokens()`, which previously let the synthesized `max_tokens` (caller room + thinking budget) go out unbounded and 400 upstream ([#10139](https://github.com/diegosouzapw/OmniRoute/issues/10139)) diff --git a/changelog.d/fixes/10140-conol-web-import-depth.md b/changelog.d/fixes/10140-conol-web-import-depth.md deleted file mode 100644 index 9d920035b6..0000000000 --- a/changelog.d/fixes/10140-conol-web-import-depth.md +++ /dev/null @@ -1,3 +0,0 @@ -- fix(providers): correct the conol-web registry fallback-models import depth, which pointed at a - non-existent `open-sse/config/services/` and made any suite loading the provider registry fail to - resolve (#10140) diff --git a/changelog.d/fixes/10144-claude-import-cli-user-id.md b/changelog.d/fixes/10144-claude-import-cli-user-id.md deleted file mode 100644 index 0c892de04b..0000000000 --- a/changelog.d/fixes/10144-claude-import-cli-user-id.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(oauth):** Claude connections created via `claude-auth/import` now send required CLI headers on the bootstrap identity call and persist a `cliUserID` device identity, fixing intermittent "Third-party apps now draw from your extra usage" 400s on otherwise valid imported subscription tokens ([#10144](https://github.com/diegosouzapw/OmniRoute/pull/10144), fixes [#10143](https://github.com/diegosouzapw/OmniRoute/issues/10143)) diff --git a/changelog.d/fixes/10156-responses-commentary-completed-snapshot.md b/changelog.d/fixes/10156-responses-commentary-completed-snapshot.md deleted file mode 100644 index 7a976ab85d..0000000000 --- a/changelog.d/fixes/10156-responses-commentary-completed-snapshot.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** Responses-passthrough `response.completed` snapshots now drop `phase:"commentary"` items the same way live SSE frames already do, so the terminal `response.output` array no longer echoes internal commentary text that was already suppressed from the stream (#10156). diff --git a/changelog.d/fixes/10158-local-proxy-subscription.md b/changelog.d/fixes/10158-local-proxy-subscription.md deleted file mode 100644 index 76194c6d49..0000000000 --- a/changelog.d/fixes/10158-local-proxy-subscription.md +++ /dev/null @@ -1 +0,0 @@ -- fix(proxy-subscriptions): allow local/loopback proxy-subscription fetch URLs (local-first, cloud-metadata still blocked) (#10158) diff --git a/changelog.d/fixes/10162-approximate-combo-context-advisory.md b/changelog.d/fixes/10162-approximate-combo-context-advisory.md deleted file mode 100644 index 3c1bc703a0..0000000000 --- a/changelog.d/fixes/10162-approximate-combo-context-advisory.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(routing):** keep approximate Combo context estimates advisory so requests reach concrete targets instead of returning a pre-dispatch 400 ([#10162](https://github.com/diegosouzapw/OmniRoute/pull/10162)) — thanks @xz-dev diff --git a/changelog.d/fixes/10169-thinking-budget-docs-i18n.md b/changelog.d/fixes/10169-thinking-budget-docs-i18n.md deleted file mode 100644 index 131288a49a..0000000000 --- a/changelog.d/fixes/10169-thinking-budget-docs-i18n.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(settings):** document Thinking Budget modes (passthrough vs auto-strip); fix dashboard i18n key collision that showed Auto Combo routing copy on the thinking tab; clarify independence from compression/cache ([#10169](https://github.com/diegosouzapw/OmniRoute/pull/10169)) diff --git a/changelog.d/fixes/10171-instrumentation-hook-boot-fatal-log.md b/changelog.d/fixes/10171-instrumentation-hook-boot-fatal-log.md deleted file mode 100644 index 3f2c0fb028..0000000000 --- a/changelog.d/fixes/10171-instrumentation-hook-boot-fatal-log.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): guarantee a non-empty `[STARTUP] Fatal:` log line for any instrumentation-hook boot throw, not just DB-driver init failures (#10171) diff --git a/changelog.d/fixes/10183-10268-admission-heap-conditional-shed.md b/changelog.d/fixes/10183-10268-admission-heap-conditional-shed.md deleted file mode 100644 index f99bba5035..0000000000 --- a/changelog.d/fixes/10183-10268-admission-heap-conditional-shed.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): gate structural chat admission shedding on real heap pressure instead of unconditional capacity, with a bounded headroom budget so a healthy heap can no longer bypass admission control indefinitely (#10183, #10268) diff --git a/changelog.d/fixes/10202-responses-vision-bridge.md b/changelog.d/fixes/10202-responses-vision-bridge.md deleted file mode 100644 index cb5ff02038..0000000000 --- a/changelog.d/fixes/10202-responses-vision-bridge.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(guardrails):** Vision Bridge handles OpenAI Responses `input`/`input_image` requests before combo vision filtering ([#10202](https://github.com/diegosouzapw/OmniRoute/pull/10202)) — thanks @Zartharas diff --git a/changelog.d/fixes/10215-cursor-kv-after-text-toolcalls.md b/changelog.d/fixes/10215-cursor-kv-after-text-toolcalls.md deleted file mode 100644 index db0ea1df9a..0000000000 --- a/changelog.d/fixes/10215-cursor-kv-after-text-toolcalls.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cursor):** Stop truncating pending tool calls on non-composer models when a KV checkpoint arrives after text but before the `exec_mcp` frame — the KV short-circuit is now gated to the composer family where it was verified ([#10215](https://github.com/diegosouzapw/OmniRoute/issues/10215)). \ No newline at end of file diff --git a/changelog.d/fixes/10223-deepseek-responses-sse-cjk-deltas.md b/changelog.d/fixes/10223-deepseek-responses-sse-cjk-deltas.md deleted file mode 100644 index 8f3c19bb20..0000000000 --- a/changelog.d/fixes/10223-deepseek-responses-sse-cjk-deltas.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(responses):** repair corrupted SSE deltas for non-ASCII streams by keeping a single stream-aware `TextDecoder` (`{ stream: true }`) across `transform()` calls instead of recreating it per chunk and decoding without the `stream` flag. When a multi-byte UTF-8 character (CJK/emoji) was split across two TCP chunks — common in Chinese streaming text — the per-chunk decoder truncated it to `U+FFFD`, corrupting every delta while the rebuilt `*.done` snapshot stayed internally identical ([#10223](https://github.com/diegosouzapw/OmniRoute/issues/10223)) \ No newline at end of file diff --git a/changelog.d/fixes/10225-combo-context-overflow-before-compression.md b/changelog.d/fixes/10225-combo-context-overflow-before-compression.md deleted file mode 100644 index 0a678180af..0000000000 --- a/changelog.d/fixes/10225-combo-context-overflow-before-compression.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(combo):** defer the known-context-overflow hard rejection for compressible requests so compression runs before the final context gate, instead of a raw-body estimate 400'ing generic Responses clients targeting a large model before OmniRoute can shrink it ([#10225](https://github.com/diegosouzapw/OmniRoute/issues/10225)) \ No newline at end of file diff --git a/changelog.d/fixes/10228-provider-model-delete-tombstones-synced-sibling.md b/changelog.d/fixes/10228-provider-model-delete-tombstones-synced-sibling.md deleted file mode 100644 index 10005b7419..0000000000 --- a/changelog.d/fixes/10228-provider-model-delete-tombstones-synced-sibling.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** deleting a manually-added custom model no longer tombstones a provider-synced model that shares its id. `DELETE /api/provider-models` is addressed by `provider` + `model` alone, so when both a custom row and a synced row existed for one id it removed both and wrote `isDeleted:true`. `replaceSyncedAvailableModelsForConnection` then filtered that id out of every subsequent re-import, so the provider could never resync — model sync kept reporting `added: N` while the catalog stayed empty and `/v1/models` never listed the model again, even though routing to it still worked. The custom row is now removed first and its presence is treated as the operator's intent, leaving the synced sibling importable; a synced-only delete still tombstones as before (#3199, #3782 unaffected) ([#10228](https://github.com/diegosouzapw/OmniRoute/pull/10228)) — thanks @Neuron-Mr-White diff --git a/changelog.d/fixes/10229-audio-bridge-multipart-runtime.md b/changelog.d/fixes/10229-audio-bridge-multipart-runtime.md deleted file mode 100644 index 6e74c302db..0000000000 --- a/changelog.d/fixes/10229-audio-bridge-multipart-runtime.md +++ /dev/null @@ -1 +0,0 @@ -- **Audio Bridge:** fix production transcription self-loop uploads so real audio reaches the configured STT provider instead of falling back to an unavailable-provider stub ([#10229](https://github.com/diegosouzapw/OmniRoute/pull/10229)). diff --git a/changelog.d/fixes/10230-deepseek-native-max-effort.md b/changelog.d/fixes/10230-deepseek-native-max-effort.md deleted file mode 100644 index 3a681d3190..0000000000 --- a/changelog.d/fixes/10230-deepseek-native-max-effort.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** DeepSeek V4's native `max` reasoning tier is now reachable. DeepSeek accepts `reasoning_effort` `low`/`high`/`max` and maps `medium`/`xhigh` down to `high`, while OmniRoute's canonical vocabulary collapses `max` onto `xhigh` — so `{"effort":"max"}` silently resolved to `high` and the catalog never advertised a `max` tier (or its `-max` variant). Following the existing `extendCodexGpt56EffortValues` precedent, the native tier is now preserved for `deepseek`/`ds` V4 models only; the global effort vocabulary is unchanged, routed namespaces (`openrouter/deepseek/…`, `tllm/deepseek_v4`, `oc/deepseek-v4-flash-free`) keep the canonical behavior, and an explicit client `reasoning_effort` still wins ([#10230](https://github.com/diegosouzapw/OmniRoute/pull/10230)) — thanks @Neuron-Mr-White diff --git a/changelog.d/fixes/10233-freeaiapikey-endpoint-moved.md b/changelog.d/fixes/10233-freeaiapikey-endpoint-moved.md deleted file mode 100644 index cd7abc5c32..0000000000 --- a/changelog.d/fixes/10233-freeaiapikey-endpoint-moved.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** FreeAIAPIKey now targets `api.freeaiapikey.com`, the host upstream names in its `410 endpoint_moved` response — every request through the provider was failing — and its catalog is resynced to the 10 models the live `/v1/models` actually serves ([#10233](https://github.com/diegosouzapw/OmniRoute/pull/10233)) diff --git a/changelog.d/fixes/10234-monsterapi-deprecation-inert.md b/changelog.d/fixes/10234-monsterapi-deprecation-inert.md deleted file mode 100644 index 62a95d78ab..0000000000 --- a/changelog.d/fixes/10234-monsterapi-deprecation-inert.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** MonsterAPI's deprecation now actually applies — the flag was written as `isDeprecated`, a key no consumer or schema reads, so the provider kept rendering as healthy in the dashboard, the onboarding wizard and the generated provider reference ([#10234](https://github.com/diegosouzapw/OmniRoute/pull/10234)) diff --git a/changelog.d/fixes/10244-cliproxy-installer-windows-platform-detection.md b/changelog.d/fixes/10244-cliproxy-installer-windows-platform-detection.md deleted file mode 100644 index bdc134b990..0000000000 --- a/changelog.d/fixes/10244-cliproxy-installer-windows-platform-detection.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cliproxy):** read platform/arch at runtime via `os.platform()`/`os.arch()` in `binaryManager` so the embedded installer selects the Windows/ARM assets even when the release bundle is built on a Linux runner (fixes #10244) \ No newline at end of file diff --git a/changelog.d/fixes/10247-provider-icon-data-url-save.md b/changelog.d/fixes/10247-provider-icon-data-url-save.md deleted file mode 100644 index 6ad4538b86..0000000000 --- a/changelog.d/fixes/10247-provider-icon-data-url-save.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** compatible/custom providers now save valid Data URL icons and show Add/Edit save failures instead of silently doing nothing ([#10247](https://github.com/diegosouzapw/OmniRoute/pull/10247)) — thanks @xz-dev diff --git a/changelog.d/fixes/10248-custom-model-overrides.md b/changelog.d/fixes/10248-custom-model-overrides.md deleted file mode 100644 index 711e48b9d5..0000000000 --- a/changelog.d/fixes/10248-custom-model-overrides.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(models):** custom model metadata and compatible-provider context overrides now take precedence over discovered metadata, while deleting a synced model no longer creates a permanent tombstone so a later provider sync can restore it ([#10248](https://github.com/diegosouzapw/OmniRoute/pull/10248)) — thanks @jackjinke diff --git a/changelog.d/fixes/10249-dedup-hash-collision.md b/changelog.d/fixes/10249-dedup-hash-collision.md deleted file mode 100644 index f118196dfe..0000000000 --- a/changelog.d/fixes/10249-dedup-hash-collision.md +++ /dev/null @@ -1 +0,0 @@ -- fix(open-sse): stop concurrent requests colliding on the same dedup hash for non-OpenAI target formats (#10249) diff --git a/changelog.d/fixes/10251-text-tool-call-parsing.md b/changelog.d/fixes/10251-text-tool-call-parsing.md deleted file mode 100644 index 9febe54687..0000000000 --- a/changelog.d/fixes/10251-text-tool-call-parsing.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** Text-format tool calls emitted inline by some models are now converted to proper `tool_use` blocks. Certain models (DeepSeek, Qwen) return tool invocations as `{"name":"Bash","arguments":{…}}` or `TOOL_CALL Read: {"file_path":"…"}` inside the text stream instead of the structured `tool_calls` field. Both formats leaked through the Claude translators as plain text, so Claude Code rendered the raw block and stalled instead of executing the tool. `extractXmlInvokeBlocks` (previously ``-only) now scans for all three shapes in a single pass and emits `content_block_start`/`input_json_delta`/`content_block_stop` events, in both `openai-to-claude` and `gemini-to-claude` (Antigravity) paths ([#10251](https://github.com/diegosouzapw/OmniRoute/pull/10251)) diff --git a/changelog.d/fixes/10261-provider-warning-badges.md b/changelog.d/fixes/10261-provider-warning-badges.md deleted file mode 100644 index 39720b4bf5..0000000000 --- a/changelog.d/fixes/10261-provider-warning-badges.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): make provider card warning indicators expose the interaction they advertise (#10261) diff --git a/changelog.d/fixes/10265-command-code-provider-api.md b/changelog.d/fixes/10265-command-code-provider-api.md deleted file mode 100644 index b38e4e9d2a..0000000000 --- a/changelog.d/fixes/10265-command-code-provider-api.md +++ /dev/null @@ -1 +0,0 @@ -- fix(command-code): route chat to the documented /provider/v1/chat/completions endpoint instead of the CLI-only /alpha/generate, which Command Code gates/blocks for external callers (#10265) \ No newline at end of file diff --git a/changelog.d/fixes/10272-provider-test-statuscode-propagation.md b/changelog.d/fixes/10272-provider-test-statuscode-propagation.md deleted file mode 100644 index 5102bf9c45..0000000000 --- a/changelog.d/fixes/10272-provider-test-statuscode-propagation.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** preserve validator HTTP status codes in API-key and web connection-test results so callers can distinguish authentication, rate-limit, and upstream failures ([#10272](https://github.com/diegosouzapw/OmniRoute/pull/10272)) — thanks @Zartharas diff --git a/changelog.d/fixes/10284-reasoning-probe-truncated-200.md b/changelog.d/fixes/10284-reasoning-probe-truncated-200.md deleted file mode 100644 index c3ddd311d2..0000000000 --- a/changelog.d/fixes/10284-reasoning-probe-truncated-200.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** tiny-budget reasoning probes (e.g. Claude Code's `/model` check sends `max_tokens: 1`) are answered with a valid truncated 200 instead of relaying the upstream 5xx "empty response content" — which previously also marked the connection unavailable and poisoned fallback/cooldown bookkeeping for a request that is only a probe ([#10281](https://github.com/diegosouzapw/OmniRoute/issues/10281)) — thanks @harkaranbrar7 diff --git a/changelog.d/fixes/10285-googleflow-video-wrong-path-auth.md b/changelog.d/fixes/10285-googleflow-video-wrong-path-auth.md deleted file mode 100644 index 8e2301cb7c..0000000000 --- a/changelog.d/fixes/10285-googleflow-video-wrong-path-auth.md +++ /dev/null @@ -1 +0,0 @@ -- fix(video): stop advertising the googleflow (Veo) video provider as working and fail fast with a clear diagnostic — its submit/poll endpoints 404 and no server-side OAuth transport can satisfy the working endpoint (#10285) diff --git a/changelog.d/fixes/10293-windows-tailscale-branches.md b/changelog.d/fixes/10293-windows-tailscale-branches.md deleted file mode 100644 index 2ee9f0d1d8..0000000000 --- a/changelog.d/fixes/10293-windows-tailscale-branches.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(build):** stop Turbopack from dead-code-eliminating the Windows Tailscale branches of `src/lib/tailscaleTunnel.ts` in the published build (#10293). The release `dist` is bundled on a Linux runner, and the bundler constant-folds `process.platform`, pruning every non-Linux branch — the Windows installers shipped with no `where` lookup, an always-injected `--socket`, and a lost `net start Tailscale`/windows-default-binary path. The module now reads the platform at runtime via `os.platform()` (a function call a bundler cannot fold), so the Windows branches survive on any build machine; a vitest regression test mocking `os.platform()` → `win32` guards the anti-fold invariant (RED before, GREEN after). \ No newline at end of file diff --git a/changelog.d/fixes/10311-healthcheck-lifecycle-default.md b/changelog.d/fixes/10311-healthcheck-lifecycle-default.md deleted file mode 100644 index 8a27b45d5d..0000000000 --- a/changelog.d/fixes/10311-healthcheck-lifecycle-default.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(ops):** Docker HEALTHCHECK defaults to the lightweight `/healthz` lifecycle probe instead of the heavy `/api/monitoring/health` path, with an `OMNIROUTE_HEALTHCHECK_PATH` opt-in override ([#10311](https://github.com/diegosouzapw/OmniRoute/pull/10311)) \ No newline at end of file diff --git a/changelog.d/fixes/10313-catalog-cache-key-hash.md b/changelog.d/fixes/10313-catalog-cache-key-hash.md deleted file mode 100644 index 5c85689004..0000000000 --- a/changelog.d/fixes/10313-catalog-cache-key-hash.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): hash the API key before using it as the model-catalog cache Map key (no raw credentials in process heap) (#10313) diff --git a/changelog.d/fixes/10314-combo-error-aggregation.md b/changelog.d/fixes/10314-combo-error-aggregation.md deleted file mode 100644 index 7dd3ef6a60..0000000000 --- a/changelog.d/fixes/10314-combo-error-aggregation.md +++ /dev/null @@ -1 +0,0 @@ -- fix(resilience): keep combo quality and auth failure reasons separate and redact connection labels in terminal errors (#10314) diff --git a/changelog.d/fixes/10319-live-ws-heartbeat-ping.md b/changelog.d/fixes/10319-live-ws-heartbeat-ping.md deleted file mode 100644 index 91ed7b00c5..0000000000 --- a/changelog.d/fixes/10319-live-ws-heartbeat-ping.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): send periodic WS heartbeat pings so live dashboard connections stop dropping every ~35s (#10319) diff --git a/changelog.d/fixes/10322-process-wide-admission-budget.md b/changelog.d/fixes/10322-process-wide-admission-budget.md deleted file mode 100644 index defab2a7fe..0000000000 --- a/changelog.d/fixes/10322-process-wide-admission-budget.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(chat-body-admission):** restore a single process-wide admission budget — heavyweight leases and queued bytes are now bounded once for the whole process instead of per session, so one session can no longer mint extra capacity or starve others; per-session fairness is preserved via round-robin dispatch ([#10110](https://github.com/diegosouzapw/OmniRoute/issues/10110)) diff --git a/changelog.d/fixes/10329-zai-web-auth-semantics.md b/changelog.d/fixes/10329-zai-web-auth-semantics.md deleted file mode 100644 index c4e6703112..0000000000 --- a/changelog.d/fixes/10329-zai-web-auth-semantics.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** validate Z.ai web Local Storage sessions against the authenticated user-settings endpoint and preserve exact upstream status codes ([#10329](https://github.com/diegosouzapw/OmniRoute/pull/10329)) — thanks @Zartharas diff --git a/changelog.d/fixes/10345-bare-combo-opencode-ids.md b/changelog.d/fixes/10345-bare-combo-opencode-ids.md deleted file mode 100644 index c3a6a499ec..0000000000 --- a/changelog.d/fixes/10345-bare-combo-opencode-ids.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(opencode-plugin):** publish bare combo model ids without the plugin provider prefix so OpenCode can select them ([#10345](https://github.com/diegosouzapw/OmniRoute/issues/10345)) diff --git a/changelog.d/fixes/10346-empty-pool-warn-once.md b/changelog.d/fixes/10346-empty-pool-warn-once.md deleted file mode 100644 index e4b50ef3ff..0000000000 --- a/changelog.d/fixes/10346-empty-pool-warn-once.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(backend):** log `auto/ matched no connected models` once per process per label instead of every minute ([#10346](https://github.com/diegosouzapw/OmniRoute/issues/10346)) diff --git a/changelog.d/fixes/10348-default-logs-redact-client.md b/changelog.d/fixes/10348-default-logs-redact-client.md deleted file mode 100644 index 4c3aa0a00f..0000000000 --- a/changelog.d/fixes/10348-default-logs-redact-client.md +++ /dev/null @@ -1 +0,0 @@ -- fix(backend): redact client IPs and account prefixes from default proxy logs (#10348) diff --git a/changelog.d/fixes/10352-github-access-token-health.md b/changelog.d/fixes/10352-github-access-token-health.md deleted file mode 100644 index 732f6ef713..0000000000 --- a/changelog.d/fixes/10352-github-access-token-health.md +++ /dev/null @@ -1 +0,0 @@ -- **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 diff --git a/changelog.d/fixes/10353-memory-heap-conflict-warn.md b/changelog.d/fixes/10353-memory-heap-conflict-warn.md deleted file mode 100644 index c52b7cc15c..0000000000 --- a/changelog.d/fixes/10353-memory-heap-conflict-warn.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(docker):** warn at boot when `OMNIROUTE_MEMORY_MB` disagrees with `NODE_OPTIONS --max-old-space-size`, and document that the standalone/Docker launcher appends `OMNIROUTE_MEMORY_MB` last ([#10353](https://github.com/diegosouzapw/OmniRoute/issues/10353)) diff --git a/changelog.d/fixes/10365-gitlab-duo-401-fallback.md b/changelog.d/fixes/10365-gitlab-duo-401-fallback.md deleted file mode 100644 index cc05612a00..0000000000 --- a/changelog.d/fixes/10365-gitlab-duo-401-fallback.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): GitLab Duo falls back to the public Code Suggestions endpoint when direct_access returns 401 (#10365) \ No newline at end of file diff --git a/changelog.d/fixes/10372-debug-mode-default-false.md b/changelog.d/fixes/10372-debug-mode-default-false.md deleted file mode 100644 index c1a59b4fb3..0000000000 --- a/changelog.d/fixes/10372-debug-mode-default-false.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(db):** `getSettings()` defaults `debugMode` to `false` — fresh installs no longer run in debug mode (persisted `debugMode: true` is preserved) ([#10372](https://github.com/diegosouzapw/OmniRoute/pull/10372) — thanks @lamchun1110) diff --git a/changelog.d/fixes/10374-claude-tool-name-casing-normalization.md b/changelog.d/fixes/10374-claude-tool-name-casing-normalization.md deleted file mode 100644 index 9acf0e08c7..0000000000 --- a/changelog.d/fixes/10374-claude-tool-name-casing-normalization.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** Consolidate tool-name casing normalization into a single `restoreClaudeToolName` helper reused across every response path (`openai-to-claude`, `gemini-to-claude`, `stream` passthrough, xAI and Antigravity handlers), replacing six hand-copied 7-entry casing maps. The shared helper resolves via the request-side `toolNameMap` first (preserving declared PascalCase and MCP/alias names), then the complete `TOOL_RENAME_MAP` (which already covers `glob`/`grep`/`task`/`todowrite`/`skill`/`askuserquestion`/etc.), then the `#7926` TitleCase→lowercase fallback for map-less clients. This closes the coverage gap that left `TodoWrite` and other tools failing with `Error: No such tool available: todowrite`, fixes a `ReferenceError` in `remapToolNamesInResponse`, and preserves the Gemini thought-signature persistence (`#8979`) and OpenAI→Claude `toolNameMap` restoration that must not regress ([#10374](https://github.com/diegosouzapw/OmniRoute/issues/10374)) diff --git a/changelog.d/fixes/10374-openai-compatible-responses-passthrough.md b/changelog.d/fixes/10374-openai-compatible-responses-passthrough.md deleted file mode 100644 index d735feed1c..0000000000 --- a/changelog.d/fixes/10374-openai-compatible-responses-passthrough.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(responses):** preserve native tool definitions for custom OpenAI-compatible providers when using the Responses API (`/v1/responses`). When `apiType` is set to `"responses"` (or `_omnirouteForceResponsesUpstream` is enabled), OmniRoute passes native tool shapes (`custom` with lark grammars, `namespace`, `local_shell`) directly upstream without running a lossy Responses→Chat→Responses conversion ([#10374](https://github.com/diegosouzapw/OmniRoute/issues/10374)) diff --git a/changelog.d/fixes/10381-free-tier-usage-history.md b/changelog.d/fixes/10381-free-tier-usage-history.md deleted file mode 100644 index 4009855cc0..0000000000 --- a/changelog.d/fixes/10381-free-tier-usage-history.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): Free Tier 'used this month' now includes live usage_history rows, not just the rolled-up daily summary (#10381) diff --git a/changelog.d/fixes/10393-opencode-rotate-network-throw.md b/changelog.d/fixes/10393-opencode-rotate-network-throw.md deleted file mode 100644 index b0d8e9fb1e..0000000000 --- a/changelog.d/fixes/10393-opencode-rotate-network-throw.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(executors):** OpencodeExecutor and MimocodeExecutor now rotate to the next account on network exceptions (timeout, connection refused/reset) when the failed account has a dedicated proxy, not only on 429 — a throw on one account no longer fails the whole request when other accounts remain. Accounts sharing the default egress (no proxy) fail fast instead of retrying the same outage against every account. The shared rotation mechanics (`pickAccount`/`markCooldown`/`markSuccess`) are now extracted into `accountRotation.ts`, fixing an identical unconditional-cooldown gap that pre-dated this PR in MimocodeExecutor ([#10393](https://github.com/diegosouzapw/OmniRoute/pull/10393)) diff --git a/changelog.d/fixes/10397-header-budget-warn-dedupe.md b/changelog.d/fixes/10397-header-budget-warn-dedupe.md deleted file mode 100644 index d4d117b913..0000000000 --- a/changelog.d/fixes/10397-header-budget-warn-dedupe.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** the header-budget drop warning fires once per unique dropped-header set instead of on every SSE response (warn-storm fix) ([#10397](https://github.com/diegosouzapw/OmniRoute/pull/10397) — thanks @lamchun1110) diff --git a/changelog.d/fixes/10404-streaming-terminated-empty-completion-failover.md b/changelog.d/fixes/10404-streaming-terminated-empty-completion-failover.md deleted file mode 100644 index d8441a21c1..0000000000 --- a/changelog.d/fixes/10404-streaming-terminated-empty-completion-failover.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): fail over combo streaming responses that reach `finish_reason` with zero content, reasoning, or tool_calls instead of forwarding a terminated-but-empty completion (#10404) diff --git a/changelog.d/fixes/10415-vision-bridge-combo-reroute.md b/changelog.d/fixes/10415-vision-bridge-combo-reroute.md deleted file mode 100644 index a3df3019c4..0000000000 --- a/changelog.d/fixes/10415-vision-bridge-combo-reroute.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(guardrails):** Vision Bridge now reroutes whole requests for named combos whose targets have zero vision-capable models (previously such image requests died with `capability_mismatch` when the describe path could not run), and when the fallback describe path also fails for every image the request degrades to explicit `(unavailable)` stub text instead of preserving images the combo cannot consume ([#10415](https://github.com/diegosouzapw/OmniRoute/pull/10415)) — thanks @rqzbeh diff --git a/changelog.d/fixes/10420-antigravity-geoblock-resilience.md b/changelog.d/fixes/10420-antigravity-geoblock-resilience.md deleted file mode 100644 index cb465299b2..0000000000 --- a/changelog.d/fixes/10420-antigravity-geoblock-resilience.md +++ /dev/null @@ -1,2 +0,0 @@ -- **fix(antigravity):** geo-blocked egress (Google "User location is not supported") is now classified (scoped to the Google AI surfaces that emit it: Cloud Code/Gemini Code Assist, Gemini API, Vertex), cached as a 24h per-account exclusion so routing continues with other accounts, and surfaced with an actionable message; the dashboard connection test now probes the real `streamGenerateContent` model surface instead of the non-geo-restricted OAuth userinfo endpoint ([#10420](https://github.com/diegosouzapw/OmniRoute/pull/10420)) — thanks @rqzbeh -- **fix(antigravity):** strip competing-agent identity sentences from system prompts (e.g. "You are a Claude agent, built on Anthropic's Claude Agent SDK.") that Antigravity flags and answers with 429 RESOURCE_EXHAUSTED (port of decolua/9router b566b20) ([#10420](https://github.com/diegosouzapw/OmniRoute/pull/10420)) — thanks @rqzbeh diff --git a/changelog.d/fixes/10424-antigravity-project-autocreate.md b/changelog.d/fixes/10424-antigravity-project-autocreate.md deleted file mode 100644 index 81fc6734c4..0000000000 --- a/changelog.d/fixes/10424-antigravity-project-autocreate.md +++ /dev/null @@ -1,2 +0,0 @@ -- **fix(antigravity):** accounts with an empty Cloud Code `projectId` now heal themselves — failed auto-onboarding (`onboardUser`) attempts are retried after a short backoff instead of being memoized forever, so the missing Google project is created without user action on a later request or token refresh ([#10424](https://github.com/diegosouzapw/OmniRoute/pull/10424)) — thanks @rqzbeh -- **fix(antigravity):** Google deprecated automatic project creation for standard-tier (personal) accounts — when `onboardUser` completes without a project id the account now fails fast with a clear `403 GCP_PROJECT_REQUIRED` message (no more generic 422 or delayed 429 RESOURCE_EXHAUSTED), and a manual GCP Project ID override is available in the connection editor so operators can enter their own project id ([#10424](https://github.com/diegosouzapw/OmniRoute/pull/10424)) — thanks @rqzbeh diff --git a/changelog.d/fixes/10430-antigravity-usage-envelope.md b/changelog.d/fixes/10430-antigravity-usage-envelope.md deleted file mode 100644 index 645045e7ea..0000000000 --- a/changelog.d/fixes/10430-antigravity-usage-envelope.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(usage):** read Gemini `usageMetadata` out of the antigravity `{ response: {...} }` envelope so non-streaming requests log real token usage instead of `IN 0 | OUT 0` (port of decolua/9router#59d858b) ([#10430](https://github.com/diegosouzapw/OmniRoute/pull/10430)) — thanks @rqzbeh diff --git a/changelog.d/fixes/10465-gemini-cached-tokens.md b/changelog.d/fixes/10465-gemini-cached-tokens.md deleted file mode 100644 index 0acd31720a..0000000000 --- a/changelog.d/fixes/10465-gemini-cached-tokens.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(usage):** surface Gemini `cachedContentTokenCount` into `cached_tokens` for non-streaming requests so cache-hit accounting matches the OpenAI/Claude/Responses branches and the streaming path (follow-up to the #10430 envelope fix) ([#10465](https://github.com/diegosouzapw/OmniRoute/pull/10465)) — thanks @rqzbeh diff --git a/changelog.d/fixes/10470-antigravity-byop-account-rotation.md b/changelog.d/fixes/10470-antigravity-byop-account-rotation.md deleted file mode 100644 index 9ec58e152a..0000000000 --- a/changelog.d/fixes/10470-antigravity-byop-account-rotation.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(antigravity):** automatically rotate to a sibling account when one is BYOP (GCP Project ID required, `gcp_project_required` 422) — the account is excluded from selection for 24h and the request succeeds via another account instead of failing fast; the actionable 422 is surfaced only when no sibling exists (follow-up to the #10424 BYOP fast-fail) ([#10470](https://github.com/diegosouzapw/OmniRoute/pull/10470)) — thanks @rqzbeh diff --git a/changelog.d/fixes/10479-mitm-passthrough-misroutes-unknown-hosts.md b/changelog.d/fixes/10479-mitm-passthrough-misroutes-unknown-hosts.md deleted file mode 100644 index 64a6e3733e..0000000000 --- a/changelog.d/fixes/10479-mitm-passthrough-misroutes-unknown-hosts.md +++ /dev/null @@ -1 +0,0 @@ -- fix(mitm): forward passthrough traffic to the actual requested Host instead of misrouting every non-TARGET_HOSTS request to the hardcoded Antigravity sandbox host (#10479) diff --git a/changelog.d/fixes/10482-docker-images-and-basepath.md b/changelog.d/fixes/10482-docker-images-and-basepath.md deleted file mode 100644 index c85ae91937..0000000000 --- a/changelog.d/fixes/10482-docker-images-and-basepath.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(docker):** point the bifrost sidecar at the real `ghcr.io/maximhq/bifrost:v1.6.11` tag and the cliproxyapi sidecar at the official `docker.io/eceasy/cli-proxy-api:v6.9.7` image (the previously pinned tags never existed), and complete the runtime `OMNIROUTE_BASE_PATH` subpath patch for Next 16 standalone (assetPrefix + client env + baked asset URLs) so prebuilt images respect the webpath env var ([#10482](https://github.com/diegosouzapw/OmniRoute/pull/10482)) diff --git a/changelog.d/fixes/10484-hermes-obfuscate-zwj.md b/changelog.d/fixes/10484-hermes-obfuscate-zwj.md deleted file mode 100644 index 5e1dc60de1..0000000000 --- a/changelog.d/fixes/10484-hermes-obfuscate-zwj.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): stop ZWJ-obfuscating the substring "hermes" in user messages and hostnames (#10484) diff --git a/changelog.d/fixes/10489-qdrant-health-badge.md b/changelog.d/fixes/10489-qdrant-health-badge.md deleted file mode 100644 index f9c216e8a5..0000000000 --- a/changelog.d/fixes/10489-qdrant-health-badge.md +++ /dev/null @@ -1,2 +0,0 @@ -- **fix(memory):** auto-check Qdrant health on mount and stop the false-red status badge on `/dashboard/memory?tab=engine` — the badge treated "not yet checked" (`health === null`) as a failure, so a healthy Qdrant showed red after every page refresh until "Test connection" was clicked; settings changes now also invalidate the stale result and re-check after the save persists, so a health check racing the settings PUT can no longer keep the badge red until a manual re-test ([#10489](https://github.com/diegosouzapw/OmniRoute/pull/10489)) -- **test(compression):** align source-contract tests with the merged `release/v3.8.50` base (`aa912c42a`) — accept the multi-line `providerTransport` shape in `omniglyph-chatcore-plumbing` and give the pipeline-circuit-breaker fixture a `metadata.executionStages` (both structural changes landed in the base merge) ([#10489](https://github.com/diegosouzapw/OmniRoute/pull/10489)) diff --git a/changelog.d/fixes/10508-cli-readiness-localhost-dns-delay.md b/changelog.d/fixes/10508-cli-readiness-localhost-dns-delay.md deleted file mode 100644 index 6d469fefe2..0000000000 --- a/changelog.d/fixes/10508-cli-readiness-localhost-dns-delay.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): use 127.0.0.1 for the readiness health-check poll instead of localhost, avoiding Windows DNS-resolution delays that made a healthy server report as never-ready (#10508) diff --git a/changelog.d/fixes/10517-zed-hosted-oauth-callback-port.md b/changelog.d/fixes/10517-zed-hosted-oauth-callback-port.md deleted file mode 100644 index af2a0d6b4c..0000000000 --- a/changelog.d/fixes/10517-zed-hosted-oauth-callback-port.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** zed-hosted OAuth now redirects the browser back to the dashboard's own loopback port (auto-completing the login), and the manual paste path accepts Zed's user_id/access_token callback URL instead of erroring with "No authorization code found" ([#10517](https://github.com/diegosouzapw/OmniRoute/pull/10517)) - thanks @phatchau036 \ No newline at end of file diff --git a/changelog.d/fixes/10518-token-backed-web-session-update.md b/changelog.d/fixes/10518-token-backed-web-session-update.md deleted file mode 100644 index 78ca1793b8..0000000000 --- a/changelog.d/fixes/10518-token-backed-web-session-update.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** allow token-backed web sessions stored with `authType: "cookie"` to refresh their token through the provider update API ([#10518](https://github.com/diegosouzapw/OmniRoute/pull/10518)) — thanks @Zartharas diff --git a/changelog.d/fixes/10519-token-backed-web-session-test-dispatch.md b/changelog.d/fixes/10519-token-backed-web-session-test-dispatch.md deleted file mode 100644 index 009f0bd2e5..0000000000 --- a/changelog.d/fixes/10519-token-backed-web-session-test-dispatch.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** test token-backed web sessions through their provider validator instead of the OAuth path ([#10519](https://github.com/diegosouzapw/OmniRoute/pull/10519)) — thanks @Zartharas diff --git a/changelog.d/fixes/10521-audit-extra-api-keys-redaction.md b/changelog.d/fixes/10521-audit-extra-api-keys-redaction.md deleted file mode 100644 index 41222522de..0000000000 --- a/changelog.d/fixes/10521-audit-extra-api-keys-redaction.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(compliance):** redact additional provider API keys from audit-log payloads ([#10521](https://github.com/diegosouzapw/OmniRoute/pull/10521)) — thanks @Zartharas diff --git a/changelog.d/fixes/10522-firefly-cookie-validation-alias-miss.md b/changelog.d/fixes/10522-firefly-cookie-validation-alias-miss.md deleted file mode 100644 index 3545d77ebb..0000000000 --- a/changelog.d/fixes/10522-firefly-cookie-validation-alias-miss.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): register a real Firefly auth probe under both the `firefly` alias and the `adobe-firefly` canonical id, and normalize the provider id before the generic web-cookie fallback, so a Firefly connection stops always reporting "Provider validation not supported" (#10522) diff --git a/changelog.d/fixes/10523-servicesupervisor-port-flake.md b/changelog.d/fixes/10523-servicesupervisor-port-flake.md deleted file mode 100644 index 1a98ea7fa2..0000000000 --- a/changelog.d/fixes/10523-servicesupervisor-port-flake.md +++ /dev/null @@ -1 +0,0 @@ -- fix(services): isolate probeBeforeSpawn adoption tests on distinct ports to stop the order-dependent flake (#10523) \ No newline at end of file diff --git a/changelog.d/fixes/10527-deepseek-web-context-amnesia.md b/changelog.d/fixes/10527-deepseek-web-context-amnesia.md deleted file mode 100644 index 4eadc0040a..0000000000 --- a/changelog.d/fixes/10527-deepseek-web-context-amnesia.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): auto-replay a bounded multi-turn trajectory in the DeepSeek Web prompt builder for clients that never send `tools[]`, so agentic clients like Cline stop losing the original task after a couple of turns (#10527) diff --git a/changelog.d/fixes/10528-direct-dispatcher-response-start-timeout.md b/changelog.d/fixes/10528-direct-dispatcher-response-start-timeout.md deleted file mode 100644 index 9354b02822..0000000000 --- a/changelog.d/fixes/10528-direct-dispatcher-response-start-timeout.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(network):** direct (no-proxy) egress now bounds each attempt's response-start window (default 30s, `OMNIROUTE_DIRECT_HEADERS_TIMEOUT_MS`) and retries once on a fresh no-keep-alive socket, so a silently-dropped pooled keep-alive connection can no longer stall direct providers (opencode-go, command-code) until a service restart ([#10214](https://github.com/diegosouzapw/OmniRoute/issues/10214)) diff --git a/changelog.d/fixes/10530-codex-combo-context.md b/changelog.d/fixes/10530-codex-combo-context.md deleted file mode 100644 index 29ada2699a..0000000000 --- a/changelog.d/fixes/10530-codex-combo-context.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(models):** align Codex GPT-5.6 context limits with the Codex catalog and honor model context overrides when advertising combos ([#10530](https://github.com/diegosouzapw/OmniRoute/issues/10530)) diff --git a/changelog.d/fixes/10536-llmlingua-2-2.0.5-drop-tfjs.md b/changelog.d/fixes/10536-llmlingua-2-2.0.5-drop-tfjs.md deleted file mode 100644 index 11a1845715..0000000000 --- a/changelog.d/fixes/10536-llmlingua-2-2.0.5-drop-tfjs.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(deps):** upgrade `@atjsh/llmlingua-2` from 2.0.3 to 2.0.5 and remove `@tensorflow/tfjs` from the LLMLingua SLM stack — 2.0.5 adds official Transformers.js v4 support (peers `@huggingface/transformers` at `^3.5.2 || ^4.0.0`) and 2.0.4+ no longer requires TensorFlow.js, restoring compatibility with OmniRoute's Transformers.js v4 while dropping the largest single contributor to the optional runtime footprint ([#10536](https://github.com/diegosouzapw/OmniRoute/issues/10536)) diff --git a/changelog.d/fixes/10540-deepseek-v4-efforts.md b/changelog.d/fixes/10540-deepseek-v4-efforts.md deleted file mode 100644 index 339758ebcf..0000000000 --- a/changelog.d/fixes/10540-deepseek-v4-efforts.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(deepseek):** Advertise `none`, `low`, `high`, and `max` for V4 Pro and Flash, derive OpenCode Go effort aliases from base-model metadata, and route those models through native Responses ([#10540](https://github.com/diegosouzapw/OmniRoute/pull/10540)) — thanks @jackjinke diff --git a/changelog.d/fixes/10544-a2a-tasks-timing-safe.md b/changelog.d/fixes/10544-a2a-tasks-timing-safe.md deleted file mode 100644 index f68ac49e3d..0000000000 --- a/changelog.d/fixes/10544-a2a-tasks-timing-safe.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(a2a):** use a constant-time bearer compare in `/api/a2a/tasks` via `crypto.timingSafeEqual`, matching the `tokensMatch` helper already used in `src/app/a2a/route.ts` and removing the last non-constant secret comparison in the repo ([#10544](https://github.com/diegosouzapw/OmniRoute/pull/10544)) diff --git a/changelog.d/fixes/10550-responses-reasoning-transport.md b/changelog.d/fixes/10550-responses-reasoning-transport.md deleted file mode 100644 index e2b40cdb8c..0000000000 --- a/changelog.d/fixes/10550-responses-reasoning-transport.md +++ /dev/null @@ -1 +0,0 @@ -- Preserve portable plaintext reasoning by default across streaming and non-streaming Chat Completions and Responses routes while keeping provider-bound opaque state target-compatible. Direct requests drop incompatible continuation reasoning by default; combos can explicitly skip incompatible targets without mutating the request. Known providers no longer show redundant encrypted-reasoning controls. (#10550, #10959) diff --git a/changelog.d/fixes/10553-list-models-card-hardcoded-null.md b/changelog.d/fixes/10553-list-models-card-hardcoded-null.md deleted file mode 100644 index 9f30aa6346..0000000000 --- a/changelog.d/fixes/10553-list-models-card-hardcoded-null.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): show the real model count on the "List Models" endpoint card instead of a permanent "—" (#10553) diff --git a/changelog.d/fixes/10557-fedora-hostname-bind.md b/changelog.d/fixes/10557-fedora-hostname-bind.md deleted file mode 100644 index 30eb3c6d10..0000000000 --- a/changelog.d/fixes/10557-fedora-hostname-bind.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** ignore the operating system `HOSTNAME` when choosing the server bind address on Linux and macOS, preventing startup failures when the shell hostname differs from `os.hostname()`; use `OMNIROUTE_SERVER_HOST` for explicit non-Windows configuration while preserving the legacy `HOSTNAME` fallback on Windows ([#10557](https://github.com/diegosouzapw/OmniRoute/pull/10557), closes [#10492](https://github.com/diegosouzapw/OmniRoute/issues/10492)) — thanks @redzrush101 diff --git a/changelog.d/fixes/10571-opencode-session-stability-free-tier-routing.md b/changelog.d/fixes/10571-opencode-session-stability-free-tier-routing.md deleted file mode 100644 index bdfe33165a..0000000000 --- a/changelog.d/fixes/10571-opencode-session-stability-free-tier-routing.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** OpenCode `x-opencode-session` now derives a stable, conversation-scoped fingerprint via `generateSessionId()` instead of a fresh random UUID per request, so upstream prompt caching can hit across requests in the same conversation; bare `big-pickle`/`*-free` model ids now keep routing to an active opencode-family connection even when its synced catalog is temporarily stale; and bare requests to no-auth catalog providers (e.g. `opencode`) now echo the listing-valid `/` form in `response.model` so clients validating against `/v1/models` don't warn ([#10571](https://github.com/diegosouzapw/OmniRoute/pull/10571)) diff --git a/changelog.d/fixes/10575-mcp-github-tool-search.md b/changelog.d/fixes/10575-mcp-github-tool-search.md deleted file mode 100644 index 108466845f..0000000000 --- a/changelog.d/fixes/10575-mcp-github-tool-search.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(mcp):** make GitHub skill tools discoverable through `omniroute_tool_search` diff --git a/changelog.d/fixes/10577-crof-stale-seed-catalog.md b/changelog.d/fixes/10577-crof-stale-seed-catalog.md deleted file mode 100644 index c4fa4da086..0000000000 --- a/changelog.d/fixes/10577-crof-stale-seed-catalog.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): remove 10 retired model ids from the crof seed catalog so /v1/models stops advertising models crof.ai no longer serves (#10577) diff --git a/changelog.d/fixes/10583-stt-nested-model-credential-fallback.md b/changelog.d/fixes/10583-stt-nested-model-credential-fallback.md deleted file mode 100644 index 601915df18..0000000000 --- a/changelog.d/fixes/10583-stt-nested-model-credential-fallback.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(audio):** when a prefix-matched STT provider has no credentials, retry gateways that list the same nested model id (e.g. `deepgram/nova-3` → `openrouter/deepgram/nova-3`) and mention those ids in the 400; stop documenting bare `deepgram/nova-3` as the default example ([#10583](https://github.com/diegosouzapw/OmniRoute/issues/10583)) diff --git a/changelog.d/fixes/10586-audio-alias-prefix-gap.md b/changelog.d/fixes/10586-audio-alias-prefix-gap.md deleted file mode 100644 index 845f00e7dd..0000000000 --- a/changelog.d/fixes/10586-audio-alias-prefix-gap.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): resolve the short provider-alias prefix (e.g. `el/`) advertised by GET /v1/models for audio speech, transcription and translation model ids (#10586) diff --git a/changelog.d/fixes/10589-elevenlabs-voice-mapping.md b/changelog.d/fixes/10589-elevenlabs-voice-mapping.md deleted file mode 100644 index 58efe3fd72..0000000000 --- a/changelog.d/fixes/10589-elevenlabs-voice-mapping.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): map OpenAI-compat voice names to real ElevenLabs voice_ids in direct TTS (#10589) diff --git a/changelog.d/fixes/10592-playground-chattab-endpoint-routing.md b/changelog.d/fixes/10592-playground-chattab-endpoint-routing.md deleted file mode 100644 index ca602b9122..0000000000 --- a/changelog.d/fixes/10592-playground-chattab-endpoint-routing.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): route the Playground's ChatTab "Send" through the endpoint actually selected in StudioConfigPane (`search`, `web.fetch`, etc.) instead of always POSTing to `/api/v1/chat/completions`, fixing the false "No active credentials for provider" 404 when testing search-only providers (#10592) diff --git a/changelog.d/fixes/10594-freepik-magnific-api.md b/changelog.d/fixes/10594-freepik-magnific-api.md deleted file mode 100644 index 4c1c59a701..0000000000 --- a/changelog.d/fixes/10594-freepik-magnific-api.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** Magnific Mystic is now the canonical provider (`/dashboard/providers/magnific`, `magnific/`). It uses the Magnific API (`api.magnific.com` + `x-magnific-api-key`), dashboard Test Connection validates keys without starting a paid generation, and the old `freepik` slug remains a legacy alias ([#10594](https://github.com/diegosouzapw/OmniRoute/pull/10594)) diff --git a/changelog.d/fixes/10597-combo-log-error-body.md b/changelog.d/fixes/10597-combo-log-error-body.md deleted file mode 100644 index ff6608947c..0000000000 --- a/changelog.d/fixes/10597-combo-log-error-body.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** Include the redacted upstream error body in the per-target COMBO failure log (`Model X failed, trying next`) so operators can triage a 400/500 without reproducing the request ([#10597](https://github.com/diegosouzapw/OmniRoute/issues/10597)) diff --git a/changelog.d/fixes/10601-xai-800-message-limit.md b/changelog.d/fixes/10601-xai-800-message-limit.md deleted file mode 100644 index 3dcd33ab8e..0000000000 --- a/changelog.d/fixes/10601-xai-800-message-limit.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(xai):** trim Chat Completions `messages` and Responses `input` to xAI's 800-item history cap before dispatch, so long tool loops no longer die on `413 Chat history exceeds the 800-message limit` ([#10601](https://github.com/diegosouzapw/OmniRoute/pull/10601)) diff --git a/changelog.d/fixes/10612-cli-token-machine-id-interop.md b/changelog.d/fixes/10612-cli-token-machine-id-interop.md deleted file mode 100644 index 48ec5b8e1d..0000000000 --- a/changelog.d/fixes/10612-cli-token-machine-id-interop.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** derive the machine-id token correctly under plain Node — `await import("node-machine-id")` puts the CJS exports on `.default`, so the destructured `machineIdSync` was `undefined` and the catch blanked the token, sending every management request unauthenticated; `OMNIROUTE_CLI_SALT` rotation is now honored too ([#10612](https://github.com/diegosouzapw/OmniRoute/pull/10612)) diff --git a/changelog.d/fixes/10613-setup-provider-api-key-collision.md b/changelog.d/fixes/10613-setup-provider-api-key-collision.md deleted file mode 100644 index 0b8c3095f0..0000000000 --- a/changelog.d/fixes/10613-setup-provider-api-key-collision.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** `omniroute setup --add-provider --api-key ` no longer aborts with "Provider API key is required" — Commander bound the value to the program-level `--api-key` (the OmniRoute server key), leaving the subcommand's own option undefined; `OMNIROUTE_API_KEY` now works as the error message advertised ([#10613](https://github.com/diegosouzapw/OmniRoute/pull/10613)) diff --git a/changelog.d/fixes/10615-api-models-v1-models-id-mismatch.md b/changelog.d/fixes/10615-api-models-v1-models-id-mismatch.md deleted file mode 100644 index 8cee943efa..0000000000 --- a/changelog.d/fixes/10615-api-models-v1-models-id-mismatch.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): make /api/models agree with /v1/models on synced-catalog coverage instead of reporting stale models as available (#10615) diff --git a/changelog.d/fixes/10686-combo-quota-token-limit-await.md b/changelog.d/fixes/10686-combo-quota-token-limit-await.md deleted file mode 100644 index a9e7b910e3..0000000000 --- a/changelog.d/fixes/10686-combo-quota-token-limit-await.md +++ /dev/null @@ -1 +0,0 @@ -- **Combo routing:** await each connection's token limit before reserving quota. The old lookup treated the `Promise` as a connection and dropped `rateLimitOverrides.tpm` ([#10686](https://github.com/diegosouzapw/OmniRoute/pull/10686)). diff --git a/changelog.d/fixes/10702-vision-bridge-alias-credential-mismatch.md b/changelog.d/fixes/10702-vision-bridge-alias-credential-mismatch.md deleted file mode 100644 index dcd1c488ae..0000000000 --- a/changelog.d/fixes/10702-vision-bridge-alias-credential-mismatch.md +++ /dev/null @@ -1 +0,0 @@ -- fix(guardrails): resolve the public provider alias before querying credentials in the Vision Bridge router, so command-code/opencode (and any alias!=id provider) are no longer reported as "unusable" despite active connections (#10702) diff --git a/changelog.d/fixes/10703-modality-bridge-vision-model-filter.md b/changelog.d/fixes/10703-modality-bridge-vision-model-filter.md deleted file mode 100644 index 1cefad69a5..0000000000 --- a/changelog.d/fixes/10703-modality-bridge-vision-model-filter.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): filter the Modality Bridge Vision model picker to vision-capable models, matching the sibling Video/Audio tabs (#10703) diff --git a/changelog.d/fixes/10705-zero-input-token-sanitization-bug.md b/changelog.d/fixes/10705-zero-input-token-sanitization-bug.md deleted file mode 100644 index aa22dbd64a..0000000000 --- a/changelog.d/fixes/10705-zero-input-token-sanitization-bug.md +++ /dev/null @@ -1 +0,0 @@ -- fix(usage): repair provider-reported input_tokens: 0 on non-trivial requests instead of passing it through unrepaired (#10705) diff --git a/changelog.d/fixes/10710-10711-cli-tools-timeout-hermes-keyid.md b/changelog.d/fixes/10710-10711-cli-tools-timeout-hermes-keyid.md deleted file mode 100644 index 4d9a6ba0b4..0000000000 --- a/changelog.d/fixes/10710-10711-cli-tools-timeout-hermes-keyid.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): distinguish a CLI-probe timeout from a genuinely absent binary in locateCommand, and resolve the Hermes Agent Apply flow's `keyId` server-side instead of writing the `YOUR_OMNIROUTE_API_KEY_HERE` placeholder (#10710, #10711) diff --git a/changelog.d/fixes/10713-runtime-repair-npm12-allow-scripts.md b/changelog.d/fixes/10713-runtime-repair-npm12-allow-scripts.md deleted file mode 100644 index 17c59d47c0..0000000000 --- a/changelog.d/fixes/10713-runtime-repair-npm12-allow-scripts.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): pass --allow-scripts for the runtime's own npm-installed dependencies, so npm 12+'s default install-scripts block no longer silently skips better-sqlite3's native build (#10713) diff --git a/changelog.d/fixes/10714-provider-metrics-ghost-deleted-provider.md b/changelog.d/fixes/10714-provider-metrics-ghost-deleted-provider.md deleted file mode 100644 index 050728ec08..0000000000 --- a/changelog.d/fixes/10714-provider-metrics-ghost-deleted-provider.md +++ /dev/null @@ -1 +0,0 @@ -- fix(db): filter `getProviderMetrics()` to providers with a live `provider_connections` row so a deleted provider stops permanently ghost-haunting the Home "Provider Topology" widget (#10714) diff --git a/changelog.d/fixes/10720-proxy-password-only-auth.md b/changelog.d/fixes/10720-proxy-password-only-auth.md deleted file mode 100644 index ca51ccba65..0000000000 --- a/changelog.d/fixes/10720-proxy-password-only-auth.md +++ /dev/null @@ -1 +0,0 @@ -- fix(proxy): keep password-only proxy credentials instead of dropping them when no username is set (#10720) diff --git a/changelog.d/fixes/10727-meta-ai-ws-timeout-diagnostics.md b/changelog.d/fixes/10727-meta-ai-ws-timeout-diagnostics.md deleted file mode 100644 index f204684baa..0000000000 --- a/changelog.d/fixes/10727-meta-ai-ws-timeout-diagnostics.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(executors):** the Meta AI (muse-spark-web) WebSocket send-message timeout now reports the socket's `readyState` at the moment it fires, so a "Meta AI WS timed out" failure can be told apart as either the connection never opening (`readyState=0`) or opening successfully and then going silent (`readyState=1`) — the exact ambiguity that made #10727 undiagnosable from logs alone (#10727). diff --git a/changelog.d/fixes/10732-copilot-m365-invocation-refresh.md b/changelog.d/fixes/10732-copilot-m365-invocation-refresh.md deleted file mode 100644 index acbfbbe693..0000000000 --- a/changelog.d/fixes/10732-copilot-m365-invocation-refresh.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** copilot-m365-web chat turns no longer surface as `(empty response)` — the type:4 invocation is aligned with the 2026-08 wire shape and now carries its type:1 Metrics follow-up in the same socket write, and the access token pre-flight-refreshes from a stored refresh_token instead of requiring a DevTools re-capture every ~75 minutes ([#10732](https://github.com/diegosouzapw/OmniRoute/pull/10732) — thanks @acc0mplish) diff --git a/changelog.d/fixes/10734-combo-context-generic-default.md b/changelog.d/fixes/10734-combo-context-generic-default.md deleted file mode 100644 index 988c435d4e..0000000000 --- a/changelog.d/fixes/10734-combo-context-generic-default.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(catalog):** stop counting `getTokenLimit()`'s generic 128k catch-all as a known combo window, so `/v1/models` advertises the min of sourced member contexts instead of collapsing a 500k combo to 128k ([#10734](https://github.com/diegosouzapw/OmniRoute/issues/10734)) diff --git a/changelog.d/fixes/10735-search-provider-named-errors.md b/changelog.d/fixes/10735-search-provider-named-errors.md deleted file mode 100644 index 0e82f36aa8..0000000000 --- a/changelog.d/fixes/10735-search-provider-named-errors.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(search):** name `/v1/search` 502s with provider id and sanitized Node cause code, without hostnames ([#10735](https://github.com/diegosouzapw/OmniRoute/issues/10735)) diff --git a/changelog.d/fixes/10736-corrupt-rotate-fence.md b/changelog.d/fixes/10736-corrupt-rotate-fence.md deleted file mode 100644 index dd2abc4fc4..0000000000 --- a/changelog.d/fixes/10736-corrupt-rotate-fence.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(db):** pause call-log rotation and record SQLITE_CORRUPT on `/api/db/health` instead of retrying writes against a malformed pager ([#10736](https://github.com/diegosouzapw/OmniRoute/issues/10736)) diff --git a/changelog.d/fixes/10765-rtk-unconditional-stats-cpu.md b/changelog.d/fixes/10765-rtk-unconditional-stats-cpu.md deleted file mode 100644 index ff36462d47..0000000000 --- a/changelog.d/fixes/10765-rtk-unconditional-stats-cpu.md +++ /dev/null @@ -1 +0,0 @@ -- fix(compression): skip the expensive `createCompressionStats()` pass in RTK when no message was actually compressed, matching every sibling stacked engine (#10765) diff --git a/changelog.d/fixes/10769-cache-stats-real-cache.md b/changelog.d/fixes/10769-cache-stats-real-cache.md deleted file mode 100644 index baaacc660d..0000000000 --- a/changelog.d/fixes/10769-cache-stats-real-cache.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** `/api/cache/stats` reported the prompt-cache LRU, which no request path ever writes to — it answered `0 hit / 0 miss, size 0` while the semantic cache served real traffic, and the Health and Usage dashboards rendered that as fact. It now reports the semantic cache's in-memory entries, with the same response shape ([#PRNUM](https://github.com/diegosouzapw/OmniRoute/pull/10769)) — thanks @Poid-ZA, who first fixed this in #9446. diff --git a/changelog.d/fixes/10770-console-interceptor-message-fidelity.md b/changelog.d/fixes/10770-console-interceptor-message-fidelity.md deleted file mode 100644 index c35260f36a..0000000000 --- a/changelog.d/fixes/10770-console-interceptor-message-fidelity.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(logging):** the app log is filterable and readable again. Entries from the tagged logger (`[LEVEL] [TAG] message`) were filed under the level instead of the component, and printf format strings were never applied, so `%s`/`%d` stayed literal with the values trailing behind them unlabelled — including every LiveWS connection line, where the format is deliberate hardening against injected format specifiers ([#PRNUM](https://github.com/diegosouzapw/OmniRoute/pull/10770)). diff --git a/changelog.d/fixes/10774-claude-code-flat-rate.md b/changelog.d/fixes/10774-claude-code-flat-rate.md deleted file mode 100644 index ea09e2b208..0000000000 --- a/changelog.d/fixes/10774-claude-code-flat-rate.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(analytics):** Claude Code (`claude`/`cc`) is a flat-rate subscription, so cost analytics reports `$0` for it instead of estimating Anthropic list prices — the metered `anthropic` API keeps its real cost, and budget/quota/routing still estimate as before ([#10774](https://github.com/diegosouzapw/OmniRoute/pull/10774)) — thanks @electrumguy diff --git a/changelog.d/fixes/10781-wal-truncate-scheduler.md b/changelog.d/fixes/10781-wal-truncate-scheduler.md deleted file mode 100644 index 4eb13a271b..0000000000 --- a/changelog.d/fixes/10781-wal-truncate-scheduler.md +++ /dev/null @@ -1 +0,0 @@ -- fix(db): periodically run `wal_checkpoint(TRUNCATE)` so the SQLite WAL file shrinks on long-running servers (default 6h, override with `OMNIROUTE_WAL_TRUNCATE_INTERVAL_MS`, `0` disables) (#10781) diff --git a/changelog.d/fixes/10782-ws-heartbeat-ping-pong.md b/changelog.d/fixes/10782-ws-heartbeat-ping-pong.md deleted file mode 100644 index 23aeaf3d3a..0000000000 --- a/changelog.d/fixes/10782-ws-heartbeat-ping-pong.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): replace LiveWS's application-only liveness check with a protocol-level `ws.ping()`/`pong` heartbeat (RFC 6455 §5.5.2) alongside the existing one, so a read-only dashboard subscriber that never sends anything survives the connection timeout — a socket that stops reading frames entirely is still reaped exactly as before (#10782) diff --git a/changelog.d/fixes/10788-ollama-cloud-effort-tiers.md b/changelog.d/fixes/10788-ollama-cloud-effort-tiers.md deleted file mode 100644 index 0437576d38..0000000000 --- a/changelog.d/fixes/10788-ollama-cloud-effort-tiers.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(open-sse):** declare `supportedThinkingEfforts` (`low`/`medium`/`high`/`max`) on Ollama Cloud's `glm-5.1`, `glm-5.2`, `deepseek-v4-pro` and `deepseek-v4-flash` registry entries so the catalog's `appendSyncedEffortVariants()` pass — which only synthesizes selectable `-low`/`-high`/`-max` model ids from an already-populated `capabilities.effort_tiers` — can expose an effort selector for these reasoning-capable models, matching what `gpt-oss:20b`/`gpt-oss:120b` already had (#10788) diff --git a/changelog.d/fixes/10792-double-transport-retry-scope.md b/changelog.d/fixes/10792-double-transport-retry-scope.md deleted file mode 100644 index 337b680add..0000000000 --- a/changelog.d/fixes/10792-double-transport-retry-scope.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** scope the same-account transport retry (#9708) out of emergency-fallback and combo hops — it was retrying the free fallback model and combo targets too, doubling upstream calls and corrupting the terminal error status on those paths. diff --git a/changelog.d/fixes/10798-respect-log-level-provider-catalog.md b/changelog.d/fixes/10798-respect-log-level-provider-catalog.md deleted file mode 100644 index 3a11aab909..0000000000 --- a/changelog.d/fixes/10798-respect-log-level-provider-catalog.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(opencode-plugin):** respect log level in provider.models() catalog path so debug/info/warn messages are suppressed when `features.logLevel` is set to `"error"` ([#10798](https://github.com/diegosouzapw/OmniRoute/pull/10798)) — thanks @tientien17 diff --git a/changelog.d/fixes/10799-provider-health-inconclusive-probes.md b/changelog.d/fixes/10799-provider-health-inconclusive-probes.md deleted file mode 100644 index 72aacacee0..0000000000 --- a/changelog.d/fixes/10799-provider-health-inconclusive-probes.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** Keep NVIDIA timeout probes and generic Antigravity/AGY HTTP 400 probes from poisoning credential health while preserving explicit Google geo-block handling ([#10799](https://github.com/diegosouzapw/OmniRoute/pull/10799)) — thanks @Zartharas diff --git a/changelog.d/fixes/10815-kiro-oauth-profilearn-dedup.md b/changelog.d/fixes/10815-kiro-oauth-profilearn-dedup.md deleted file mode 100644 index 51768aab4c..0000000000 --- a/changelog.d/fixes/10815-kiro-oauth-profilearn-dedup.md +++ /dev/null @@ -1 +0,0 @@ -- fix(db): disambiguate `createProviderConnection()`'s OAuth email dedup by `providerSpecificData.profileArn` in addition to `username`, so adding a second Kiro/AWS profile with the same email creates a new connection instead of silently merging into the first (#10815) diff --git a/changelog.d/fixes/10815-kiro-social-multi-account.md b/changelog.d/fixes/10815-kiro-social-multi-account.md deleted file mode 100644 index 45b2cfed59..0000000000 --- a/changelog.d/fixes/10815-kiro-social-multi-account.md +++ /dev/null @@ -1 +0,0 @@ -- 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) diff --git a/changelog.d/fixes/10832-unprefixed-dalle3.md b/changelog.d/fixes/10832-unprefixed-dalle3.md deleted file mode 100644 index 2dfd970b13..0000000000 --- a/changelog.d/fixes/10832-unprefixed-dalle3.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(images):** register OpenAI `dall-e-3` in the image registry so unprefixed `dall-e-3` (and `openai/dall-e-3`) route to OpenAI Images instead of Microsoft Designer Web, and so the chat catalog no longer lists `openai/dall-e-3` as a 128k chat model ([#10832](https://github.com/diegosouzapw/OmniRoute/issues/10832)) diff --git a/changelog.d/fixes/10843-outbound-guard-mapped-ipv4.md b/changelog.d/fixes/10843-outbound-guard-mapped-ipv4.md deleted file mode 100644 index 2894ff65b0..0000000000 --- a/changelog.d/fixes/10843-outbound-guard-mapped-ipv4.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(security):** Outbound URL guard now resolves IPv4-mapped IPv6 literals to their embedded address, so `[::ffff:169.254.169.254]` is refused by the unconditional cloud-metadata block like its dotted spelling; `[::]` is refused alongside `0.0.0.0` ([#10843](https://github.com/diegosouzapw/OmniRoute/pull/10843)) — thanks @ntdat812 diff --git a/changelog.d/fixes/10848-image-scan-cookie-bridge.md b/changelog.d/fixes/10848-image-scan-cookie-bridge.md deleted file mode 100644 index 07e0f20291..0000000000 --- a/changelog.d/fixes/10848-image-scan-cookie-bridge.md +++ /dev/null @@ -1 +0,0 @@ -- fix(config): exclude cookie-auth image bridges (chatgpt-web, gemini-web) from the unprefixed model scan so a bare id never silently binds to an unofficial web bridge (#10848) diff --git a/changelog.d/fixes/10849-search-provider-opaque-400.md b/changelog.d/fixes/10849-search-provider-opaque-400.md deleted file mode 100644 index a8982fb194..0000000000 --- a/changelog.d/fixes/10849-search-provider-opaque-400.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): POST /v1/search now replies with a named `Unknown search provider: ` error (and field-named validation messages) instead of an opaque `Invalid request` for unrecognized or short-alias provider ids like `brave`/`serper` (#10849) diff --git a/changelog.d/fixes/10850-readyz-alias.md b/changelog.d/fixes/10850-readyz-alias.md deleted file mode 100644 index 94e62739ba..0000000000 --- a/changelog.d/fixes/10850-readyz-alias.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** alias `GET`/`HEAD` `/readyz` to `/healthz` so Kubernetes readiness probes do not 404 ([#10850](https://github.com/diegosouzapw/OmniRoute/issues/10850)) diff --git a/changelog.d/fixes/10851-openapi-spec-auth-contract.md b/changelog.d/fixes/10851-openapi-spec-auth-contract.md deleted file mode 100644 index e2b038592c..0000000000 --- a/changelog.d/fixes/10851-openapi-spec-auth-contract.md +++ /dev/null @@ -1 +0,0 @@ -- Document the conditional management authentication and 401/403 responses for `GET /api/openapi/spec`. diff --git a/changelog.d/fixes/10853-i18n-disabled-mistranslation.md b/changelog.d/fixes/10853-i18n-disabled-mistranslation.md deleted file mode 100644 index 836cc6491e..0000000000 --- a/changelog.d/fixes/10853-i18n-disabled-mistranslation.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(i18n):** The "Disabled" status no longer renders as the noun for a person with a disability in Japanese, Spanish, Hindi, Polish, Telugu, Urdu and both Chinese locales — 24 strings now use each catalog's existing wording (ja 無効, es Deshabilitado, hi अक्षम, pl Wyłączone, te నిలిపివేయబడింది, ur غیر فعال, zh-CN 已禁用, zh-TW 已停用) ([#10812](https://github.com/diegosouzapw/OmniRoute/issues/10812), [#10853](https://github.com/diegosouzapw/OmniRoute/pull/10853)) — thanks @ntdat812 diff --git a/changelog.d/fixes/10854-skills-marketplace-owner.md b/changelog.d/fixes/10854-skills-marketplace-owner.md deleted file mode 100644 index e80a109f77..0000000000 --- a/changelog.d/fixes/10854-skills-marketplace-owner.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(skills):** Marketplace-installed skills are available to API-key-scoped requests, including existing SkillsMP and skills.sh installs ([#10854](https://github.com/diegosouzapw/OmniRoute/pull/10854)) — thanks @kriptoburak diff --git a/changelog.d/fixes/10857-hide-auto-models-when-routing-disabled.md b/changelog.d/fixes/10857-hide-auto-models-when-routing-disabled.md deleted file mode 100644 index 39da596ee3..0000000000 --- a/changelog.d/fixes/10857-hide-auto-models-when-routing-disabled.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(catalog):** `/v1/models` no longer advertises the built-in `auto/*` ids while auto routing is disabled — they were listed but rejected at request time with `Auto routing is disabled` ([#10831](https://github.com/diegosouzapw/OmniRoute/issues/10831), [#10857](https://github.com/diegosouzapw/OmniRoute/pull/10857)) — thanks @ntdat812 diff --git a/changelog.d/fixes/10858-base64-file-token-estimate.md b/changelog.d/fixes/10858-base64-file-token-estimate.md deleted file mode 100644 index 18d8104b10..0000000000 --- a/changelog.d/fixes/10858-base64-file-token-estimate.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(context):** Base64 file payloads (OpenAI `file` parts, Responses `input_file`, Claude `document` blocks) are budgeted like the Gemini `inlineData` path instead of being counted as prompt text — a ~1MB PDF estimated at 350k tokens and was rejected on the context limit before reaching the provider's document pipeline ([#10840](https://github.com/diegosouzapw/OmniRoute/issues/10840), [#10858](https://github.com/diegosouzapw/OmniRoute/pull/10858)) — thanks @ntdat812 diff --git a/changelog.d/fixes/10860-mcp-upstream-fetch-timeout.md b/changelog.d/fixes/10860-mcp-upstream-fetch-timeout.md deleted file mode 100644 index a23aeed2a1..0000000000 --- a/changelog.d/fixes/10860-mcp-upstream-fetch-timeout.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(mcp):** MCP tool calls that wait on a model provider no longer abort after 10 seconds. `omniRouteFetch` applied a single hardcoded `AbortSignal.timeout(10000)` to every internal hop, and `omniroute_route_request` — which posts to `/v1/chat/completions` and waits on the upstream provider, plus auto-combo candidate probing before a provider is even chosen — passed no signal of its own, so it inherited it. Any route slower than 10s failed from the MCP side while the identical request succeeded through the REST API. `omniroute_web_search` and `omniroute_web_fetch` in the same file already carried an explicit 60s signal, so that value is now shared by all three provider-bound calls instead of being repeated as a literal, while management reads (health, resilience, rate limits, combos, quota, usage) keep their fast-fail 10s budget so a stalled local endpoint still cannot hold a tool call open. Both budgets are overridable through `OMNIROUTE_MCP_FETCH_TIMEOUT_MS` and `OMNIROUTE_MCP_UPSTREAM_TIMEOUT_MS`, replacing the reported workaround of patching the compiled `dist/.build/next/server/chunks/*.js`; a malformed or non-positive override falls back to the default rather than disabling the timeout diff --git a/changelog.d/fixes/10862-sync-models-degraded-cached-catalog.md b/changelog.d/fixes/10862-sync-models-degraded-cached-catalog.md deleted file mode 100644 index fd6f7d3f04..0000000000 --- a/changelog.d/fixes/10862-sync-models-degraded-cached-catalog.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** importing models with an expired API key now surfaces the credential error instead of reporting "No new models were added". The Import button posts to `/api/providers/{id}/sync-models`, which self-fetches the models route; that route does not fail on an upstream 401 but degrades to a catalog it already has, preferring the cache and using the local catalog only when there is no cache. A provider that imported successfully once therefore has a cache, so an expired key produced `{ source: "cache", warning: "Models probe failed (401) — using cached catalog" }` with HTTP 200 — and the #5460/#5465 degradation guard only recognised the `local_catalog` branch, so model-sync accepted it as a successful discovery, found every cached model already imported, and returned the empty-diff result. Retest does not go through this path, which is why it failed correctly and made the import look like a genuine "nothing to do". The existing rule — a degraded discovery must not be persisted as the synced catalog — is now applied to the branch it missed rather than special-casing 401/403, discriminating on the warning the fallback builder always attaches (an ordinary non-refresh cache hit attaches none, and model-sync always requests `refresh=true`). `isDegradedLocalCatalog` keeps its exact meaning and its existing tests diff --git a/changelog.d/fixes/10866-combo-empty-models.md b/changelog.d/fixes/10866-combo-empty-models.md deleted file mode 100644 index e71092d5d4..0000000000 --- a/changelog.d/fixes/10866-combo-empty-models.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): reject a combo update that removes every model, and store the copilot's combo targets where the router reads them (#10866) diff --git a/changelog.d/fixes/10868-proxy-echo-ipv4-fallback.md b/changelog.d/fixes/10868-proxy-echo-ipv4-fallback.md deleted file mode 100644 index 91f4e717e8..0000000000 --- a/changelog.d/fixes/10868-proxy-echo-ipv4-fallback.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(proxy):** proxy "Test connection" no longer reports an IPv4-only SOCKS5/SSH proxy as dead. #1255 moved every egress probe from `api.ipify.org` to `api64.ipify.org` so proxies with IPv6 egress could be tested, but `api64` is IPv6-first: a tunnel with no IPv6 route has nothing to connect to, so the probe hung until the caller's deadline and a proxy that was carrying live LLM traffic came back as a failure. Swapping the target to `api4` fixes that case and re-breaks the one #1255 fixed, so the probe now tries the targets in order instead — `api64` first, so a proxy with working IPv6 answers on the first attempt and keeps the exact behaviour #1255 introduced, including which of its addresses is reported (the egress IP is used as an identity to detect accounts of one rotation group sharing an address, so the attempts are sequential rather than raced). The attempts split the budget each call site already enforced, so no probe can take longer than it could before, and each attempt gets its own `AbortController` so exhausting the budget on an unreachable target does not abort the next one. `OMNIROUTE_PROXY_ECHO_URL` pins a single target — including a self-hosted echo — replacing the workaround of rewriting the compiled bundle after every upgrade. The relay branch of the test route still targets `api64` through `x-relay-target`, since that request egresses from the relay worker rather than the operator's tunnel diff --git a/changelog.d/fixes/10870-cli-env-collision.md b/changelog.d/fixes/10870-cli-env-collision.md deleted file mode 100644 index 95a428ba08..0000000000 --- a/changelog.d/fixes/10870-cli-env-collision.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): warn when a .env line never takes effect, and stop swallowing an unreadable .env (#10870) diff --git a/changelog.d/fixes/10873-mimocode-retirement-state-cleanup.md b/changelog.d/fixes/10873-mimocode-retirement-state-cleanup.md deleted file mode 100644 index 44443eac6c..0000000000 --- a/changelog.d/fixes/10873-mimocode-retirement-state-cleanup.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(db):** Remove stale MiMoCode provider configuration, including the legacy `mcode` alias, left after provider retirement while preserving historical usage and call logs ([#10873](https://github.com/diegosouzapw/OmniRoute/pull/10873)) — thanks @Zartharas diff --git a/changelog.d/fixes/10877-quota-alias-fetcher-lookup-gap.md b/changelog.d/fixes/10877-quota-alias-fetcher-lookup-gap.md deleted file mode 100644 index 9501c6dad2..0000000000 --- a/changelog.d/fixes/10877-quota-alias-fetcher-lookup-gap.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** `getResetAwareProvider()` and the auto-combo quota lookup in `combo.ts` now canonicalize the provider id via `resolveProviderId()` before calling `getQuotaFetcher()`, so a fetcher registered under a provider's canonical id (e.g. `ollama-cloud`, `codex`) is found for combo targets stored under an alias spelling (e.g. `ollamacloud`, `cx`) instead of silently degrading reset-aware/reset-window/auto quota-aware routing to plain priority ordering (#10877) diff --git a/changelog.d/fixes/10878-unsupported-validation-probes-neutral.md b/changelog.d/fixes/10878-unsupported-validation-probes-neutral.md deleted file mode 100644 index 1fc7c01933..0000000000 --- a/changelog.d/fixes/10878-unsupported-validation-probes-neutral.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(provider-health):** Keep unsupported 404/405 validation probes neutral so they do not poison stored credential health or scheduler failure state, while still honoring per-connection health-check pacing ([#10878](https://github.com/diegosouzapw/OmniRoute/pull/10878)) — thanks @Zartharas diff --git a/changelog.d/fixes/10882-antigravity-gemini37-flash-tiers.md b/changelog.d/fixes/10882-antigravity-gemini37-flash-tiers.md deleted file mode 100644 index b1ff4bbf5a..0000000000 --- a/changelog.d/fixes/10882-antigravity-gemini37-flash-tiers.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(antigravity):** map Gemini 3.7 Flash tier ids (`gemini-3.7-flash-high/medium/low`, bare `gemini-3.7-flash`) to the upstream `gemini-3.7-flash-tiered` model id Google's Cloud Code endpoint expects, and configure per-tier thinking budgets ([#10882](https://github.com/diegosouzapw/OmniRoute/pull/10882)) — thanks @adevwithpurpose diff --git a/changelog.d/fixes/10887-memory-mcp-tools.md b/changelog.d/fixes/10887-memory-mcp-tools.md deleted file mode 100644 index 8dc02db1d9..0000000000 --- a/changelog.d/fixes/10887-memory-mcp-tools.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(memory):** enable agent memory save/update via MCP tools (`memory_save`/`update`/`search`/`delete` builtins with per-provider schemas, `apiKeyId` optional with caller-principal fallback) and gate server-side memory builtin injection to non-stream requests only ([#10887](https://github.com/diegosouzapw/OmniRoute/pull/10887)) — thanks @Egorich-print diff --git a/changelog.d/fixes/10902-pplx-search-hint-optin.md b/changelog.d/fixes/10902-pplx-search-hint-optin.md deleted file mode 100644 index 233fb61f19..0000000000 --- a/changelog.d/fixes/10902-pplx-search-hint-optin.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(perplexity-web):** make the built-in-search hint appended to every system message opt-in via `OMNIROUTE_PPLX_SEARCH_HINT` (off by default) — Perplexity's answer engine searches anyway, and the hint leaked into replies as meta-commentary for coding clients ([#10902](https://github.com/diegosouzapw/OmniRoute/pull/10902), extracted from [#8634](https://github.com/diegosouzapw/OmniRoute/pull/8634)) — thanks @danscMax diff --git a/changelog.d/fixes/10903-loopback-gate-memory-success.md b/changelog.d/fixes/10903-loopback-gate-memory-success.md deleted file mode 100644 index 25720ba1a8..0000000000 --- a/changelog.d/fixes/10903-loopback-gate-memory-success.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** the loopback readiness gate no longer memorizes a failed probe — the next caller after 30s starts a fresh probe, and a readiness failure is logged once per probe instead of once per caller ([#10903](https://github.com/diegosouzapw/OmniRoute/pull/10903)) diff --git a/changelog.d/fixes/10935-cloudflare-relay-path-guard.md b/changelog.d/fixes/10935-cloudflare-relay-path-guard.md deleted file mode 100644 index 0799cdc52d..0000000000 --- a/changelog.d/fixes/10935-cloudflare-relay-path-guard.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(relay):** the Cloudflare proxy-relay worker now resolves `x-relay-path` through the shared `resolveRelayTarget()` guard instead of concatenating it onto the validated target. PR #4643 and its follow-up applied that guard to the Deno and Vercel workers; the Cloudflare generator, ported separately from upstream `decolua/9router` PR #1360, kept `fetch(targetBase + relayPath)`. Validating `x-relay-target` and then concatenating is not sufficient — the path re-points the request past the host that was just checked, through userinfo (`/x@evil.com`), a backslash (`\evil.com`), or a protocol-relative path (`//evil.com/x`). The guard is embedded verbatim under a literal `const resolveRelayTarget =` binding so the hardcoded call site still resolves when the SWC-minified standalone build mangles the source function's own name (#6149), and the new regression test pins that property for this worker by renaming the embedded function and re-evaluating the emitted source. The auth check and the private/loopback target guard are unchanged diff --git a/changelog.d/fixes/10936-standalone-server-cjs-esm-scope.md b/changelog.d/fixes/10936-standalone-server-cjs-esm-scope.md deleted file mode 100644 index 824f7df647..0000000000 --- a/changelog.d/fixes/10936-standalone-server-cjs-esm-scope.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(build):** the `next` Docker image no longer crashes on boot with `ReferenceError: require is not defined in ES module scope`. The standalone `server.js` is CommonJS, but the `postbuild` colocate step was re-adding `"type":"module"` to the standalone root `package.json` (undoing `assembleStandalone`'s strip) to make its ESM worker bundles load. The `type:module` scope is now written per-worker-directory instead of on the root, so `server.js` stays CommonJS while the workers stay ESM ([#10936](https://github.com/diegosouzapw/OmniRoute/pull/10936), fixes [#10933](https://github.com/diegosouzapw/OmniRoute/issues/10933)) — thanks @arminanton diff --git a/changelog.d/fixes/10940-opencode-limit-output.md b/changelog.d/fixes/10940-opencode-limit-output.md deleted file mode 100644 index 9af54a2046..0000000000 --- a/changelog.d/fixes/10940-opencode-limit-output.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): always emit limit.output in generated OpenCode config so schema validation passes for metadata-less models (#10940) diff --git a/changelog.d/fixes/10941-relay-private-host-guard.md b/changelog.d/fixes/10941-relay-private-host-guard.md deleted file mode 100644 index 53d3aedeec..0000000000 --- a/changelog.d/fixes/10941-relay-private-host-guard.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(relay):** the private/loopback guard the three proxy-relay workers embed no longer misses four host spellings, and now lives in one place instead of three byte-identical inline copies. Driving `new URL(target).hostname` the way the workers do, the previous guard allowed `::` (the unspecified address, which reaches a service bound to the IPv6 loopback), `localhost.` (the FQDN root dot defeated the exact match and every `.localhost`/`.local`/`.internal` suffix rule, so `svc.internal.` slipped too), `::127.0.0.1` (the deprecated IPv4-compatible form — only `::ffff:` was checked), and `feb0::1` (link-local is `fe80::/10`, spanning `fe80`–`febf`, but only the literal `fe80:` spelling matched). The policy moved to `src/lib/proxyRelay/privateHostname.ts` and is embedded verbatim via `Function#toString` under a literal const name, the same mechanism `resolveRelayTarget` already uses for these workers, so a minified standalone build cannot break the call site (#6149). Nothing previously blocked is now allowed. Severity is low — reaching a worker needs the `x-relay-auth` secret and these are edge runtimes where loopback has nothing listening — but the suffix-rule bypass held regardless of runtime diff --git a/changelog.d/fixes/10945-least-used-rotation.md b/changelog.d/fixes/10945-least-used-rotation.md deleted file mode 100644 index 36b23951b2..0000000000 --- a/changelog.d/fixes/10945-least-used-rotation.md +++ /dev/null @@ -1 +0,0 @@ -- **Account rotation:** make `fallbackStrategy: "least-used"` actually rotate. The strategy sorts on `lastUsedAt` but never wrote it — only the round-robin branch committed — so on a pool where every `last_used_at` was still `NULL` the tie-break fell through to `priority` and returned the same connection on every dispatch ([#10945](https://github.com/diegosouzapw/OmniRoute/issues/10945)). diff --git a/changelog.d/fixes/10947-windows-updater-artifact-name.md b/changelog.d/fixes/10947-windows-updater-artifact-name.md deleted file mode 100644 index 10c90a216d..0000000000 --- a/changelog.d/fixes/10947-windows-updater-artifact-name.md +++ /dev/null @@ -1 +0,0 @@ -- **Desktop auto-update (Windows):** stop the in-app updater 404ing on every release. NSIS used electron-builder's default artifact name, whose spaces GitHub rewrites to `.` on upload while `latest.yml` keeps `-`, so the manifest pointed at `OmniRoute-Setup-X.Y.Z.exe` while the published asset was `OmniRoute.Setup.X.Y.Z.exe`. The name is now set explicitly to the dot form the asset already has, so nothing published changes name ([#10947](https://github.com/diegosouzapw/OmniRoute/issues/10947)). diff --git a/changelog.d/fixes/10949-mixed-reasoning-plaintext.md b/changelog.d/fixes/10949-mixed-reasoning-plaintext.md deleted file mode 100644 index 05a055ec53..0000000000 --- a/changelog.d/fixes/10949-mixed-reasoning-plaintext.md +++ /dev/null @@ -1 +0,0 @@ -- Preserve explicit plaintext reasoning when a Responses reasoning item also carries opaque provider state (rare OpenCode Go `deepseek-v4-flash` responses). Mixed plaintext + opaque input is projected onto the target transport: plaintext targets keep portable text, opaque targets keep provider state. Opaque-only reasoning is dropped when the selected target cannot replay it, allowing cross-model conversations to continue. (#10949, #10959) diff --git a/changelog.d/fixes/10953-preserve-provider-effort-tiers.md b/changelog.d/fixes/10953-preserve-provider-effort-tiers.md deleted file mode 100644 index d509aac61b..0000000000 --- a/changelog.d/fixes/10953-preserve-provider-effort-tiers.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(catalog):** preserve provider-declared reasoning effort tiers instead of replacing them with generic defaults ([#10953](https://github.com/diegosouzapw/OmniRoute/pull/10953)) — thanks @xz-dev diff --git a/changelog.d/fixes/10954-combo-create-models.md b/changelog.d/fixes/10954-combo-create-models.md deleted file mode 100644 index 0a0638bcea..0000000000 --- a/changelog.d/fixes/10954-combo-create-models.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): combo create accepts --models and no longer creates empty combos (#10954) diff --git a/changelog.d/fixes/10955-cli-ref-params.md b/changelog.d/fixes/10955-cli-ref-params.md deleted file mode 100644 index 9497b4129e..0000000000 --- a/changelog.d/fixes/10955-cli-ref-params.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): resolve $ref path params and add PATCH combos requestBody in generated API commands (#10955) diff --git a/changelog.d/fixes/10959-single-target-reasoning-fallback.md b/changelog.d/fixes/10959-single-target-reasoning-fallback.md deleted file mode 100644 index eb6e9c1903..0000000000 --- a/changelog.d/fixes/10959-single-target-reasoning-fallback.md +++ /dev/null @@ -1 +0,0 @@ -- 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)) diff --git a/changelog.d/fixes/10967-10966-combo-diag-recovery.md b/changelog.d/fixes/10967-10966-combo-diag-recovery.md deleted file mode 100644 index e962b14981..0000000000 --- a/changelog.d/fixes/10967-10966-combo-diag-recovery.md +++ /dev/null @@ -1,2 +0,0 @@ -- fix(sse): combo diagnostics no longer truncate `exhausted_connection` entries to a hardcoded `provider: "unknown"` with the provider prefix eaten by an 8-char slice — the real provider id is preserved and only the connection id is truncated (#10967) -- fix(sse): combo terminal failures caused entirely by quota/account-balance exhaustion (including a durable HTTP 403 `insufficient_quota` / `AUTHZ_INSUFFICIENT_BALANCE`) now stamp a stable `quota_exhausted` diagnostics reason with a `switch-combo` recovery hint instead of the misleading default `retry` action (#10966) diff --git a/changelog.d/fixes/10976-skip-default-searxng.md b/changelog.d/fixes/10976-skip-default-searxng.md deleted file mode 100644 index a317979b4a..0000000000 --- a/changelog.d/fixes/10976-skip-default-searxng.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(search):** skip catalog-default SearXNG `http://localhost:8888/search` so Docker/K8s search does not ECONNREFUSED then 502 into the next provider ([#10976](https://github.com/diegosouzapw/OmniRoute/issues/10976)) diff --git a/changelog.d/fixes/10986-reasoning-only-content.md b/changelog.d/fixes/10986-reasoning-only-content.md deleted file mode 100644 index 0d293482bd..0000000000 --- a/changelog.d/fixes/10986-reasoning-only-content.md +++ /dev/null @@ -1 +0,0 @@ -- fix(command-code): surface reasoning-only output as content when a model emits no text-delta (#10986) \ No newline at end of file diff --git a/changelog.d/fixes/10988-release-v3850-quality-gates.md b/changelog.d/fixes/10988-release-v3850-quality-gates.md deleted file mode 100644 index 283b30b836..0000000000 --- a/changelog.d/fixes/10988-release-v3850-quality-gates.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(ci):** clear inherited `release/v3.8.50` quality-gate reds on the X Search PR: drop the stale `copilot-m365-web.ts:330` public-creds allowlist, document six missing env vars, register four covering Stryker tap tests, prune leftover ESLint suppressions, replace the phantom `@/lib/db/connections` Utilization import with `getProviderConnectionById`, and fix open-sse/dashboard typecheck regressions in freebuff, browser-backed chat, auth, health matrix, and Monaco ([#10988](https://github.com/diegosouzapw/OmniRoute/pull/10988)). diff --git a/changelog.d/fixes/10988-release-v3850-unit-shards.md b/changelog.d/fixes/10988-release-v3850-unit-shards.md deleted file mode 100644 index 139266c990..0000000000 --- a/changelog.d/fixes/10988-release-v3850-unit-shards.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(ci):** clear remaining `release/v3.8.50` unit-shard reds on the X Search PR: pin `onnxruntime-node` to the transformers 1.24.3 copy, rebaseline OpenAPI coverage, sync goldens/i18n, honor eye-hidden no-auth models across provider aliases, await rejected-request call-log writes, absorb catalog event-loop shard contention in #9147, and align inherited tests with advisory context estimates, #10501 combo terminal-status aggregation, and current catalog/auth behavior ([#10988](https://github.com/diegosouzapw/OmniRoute/pull/10988)). diff --git a/changelog.d/fixes/10990-v0-vercel-web-static-catalog.md b/changelog.d/fixes/10990-v0-vercel-web-static-catalog.md deleted file mode 100644 index 9d56721208..0000000000 --- a/changelog.d/fixes/10990-v0-vercel-web-static-catalog.md +++ /dev/null @@ -1 +0,0 @@ -- **Static model catalog for v0-vercel-web:** seed a static catalog for the v0-vercel-web web-cookie provider (v0-1.0-md, v0-1.5-lg, v0-1.5-md) so its dashboard "Available Models" / "Import from /models" UI serves a usable list instead of falling through to the route's 400 "does not support models listing" ([#10990](https://github.com/diegosouzapw/OmniRoute/issues/10990)). \ No newline at end of file diff --git a/changelog.d/fixes/10997-blackbox-deprecation.md b/changelog.d/fixes/10997-blackbox-deprecation.md deleted file mode 100644 index 74ac191526..0000000000 --- a/changelog.d/fixes/10997-blackbox-deprecation.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): mark the blackbox provider deprecated — api.blackbox.ai returns HTTP 404 on every path variant (sweep 2026-08-21), so the public inference surface is dead and the catalog entry now carries a deprecation notice. ([#10997](https://github.com/diegosouzapw/OmniRoute/issues/10997)) \ No newline at end of file diff --git a/changelog.d/fixes/11002-dify-key-validation.md b/changelog.d/fixes/11002-dify-key-validation.md deleted file mode 100644 index 6574714c9b..0000000000 --- a/changelog.d/fixes/11002-dify-key-validation.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): validate Dify keys against its native /v1/chat-messages endpoint (#11002) \ No newline at end of file diff --git a/changelog.d/fixes/11008-account-rotation-eviction.md b/changelog.d/fixes/11008-account-rotation-eviction.md deleted file mode 100644 index 4855dde6f2..0000000000 --- a/changelog.d/fixes/11008-account-rotation-eviction.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(accounts):** `markCooldown` now carries the failure origin (`transient` vs `terminal`) — transient 429/network only cools down, repeated terminal failures evict and are skipped by `pickAccount` until a success or operator clear ([#11008](https://github.com/diegosouzapw/OmniRoute/pull/11008)) — thanks @maxmad64bis diff --git a/changelog.d/fixes/11009-terminal-status-origin.md b/changelog.d/fixes/11009-terminal-status-origin.md deleted file mode 100644 index f0ab24edaf..0000000000 --- a/changelog.d/fixes/11009-terminal-status-origin.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** route terminal `testStatus` writes (`banned`, `deactivated`, `credits_exhausted`) through a single origin-aware passage — probe failures are recorded but never deactivate the connection ([#11009](https://github.com/diegosouzapw/OmniRoute/pull/11009)) — thanks @maxmad64bis diff --git a/changelog.d/fixes/11014-codex-drop-default-on.md b/changelog.d/fixes/11014-codex-drop-default-on.md deleted file mode 100644 index 0e5a8f1129..0000000000 --- a/changelog.d/fixes/11014-codex-drop-default-on.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(codex):** drop non-standard `codex.*` SSE events by default so OpenAI SDK / Codex CLI `/v1/responses` clients are not 502'd by `event: codex.rate_limits` ([#11014](https://github.com/diegosouzapw/OmniRoute/issues/11014)) — thanks @RaviTharuma diff --git a/changelog.d/fixes/11015-shutdown-track-sse.md b/changelog.d/fixes/11015-shutdown-track-sse.md deleted file mode 100644 index 1ed99b3669..0000000000 --- a/changelog.d/fixes/11015-shutdown-track-sse.md +++ /dev/null @@ -1 +0,0 @@ -- **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 diff --git a/changelog.d/fixes/11016-cred-health-disable-log.md b/changelog.d/fixes/11016-cred-health-disable-log.md deleted file mode 100644 index 37a9715f41..0000000000 --- a/changelog.d/fixes/11016-cred-health-disable-log.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(startup):** log `Credential health scheduler disabled` when `OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK` is set instead of lying with `started` ([#11016](https://github.com/diegosouzapw/OmniRoute/issues/11016)) — thanks @RaviTharuma diff --git a/changelog.d/fixes/11017-rate-limit-docs.md b/changelog.d/fixes/11017-rate-limit-docs.md deleted file mode 100644 index fc92469bd6..0000000000 --- a/changelog.d/fixes/11017-rate-limit-docs.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(api-keys):** document that unset `DEFAULT_RATE_LIMIT_PER_DAY` is unlimited (#2289), not a hidden 1000/day cap ([#11017](https://github.com/diegosouzapw/OmniRoute/issues/11017)) — thanks @RaviTharuma diff --git a/changelog.d/fixes/11050-remove-ghost-webhook-events.md b/changelog.d/fixes/11050-remove-ghost-webhook-events.md deleted file mode 100644 index 6278ee6c0a..0000000000 --- a/changelog.d/fixes/11050-remove-ghost-webhook-events.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(webhooks):** remove 3 declared-but-never-emitted events (`provider.error`, `provider.recovered`, `combo.switched`) from `WebhookEvent` — catalog now `request.completed | request.failed | quota.exceeded | test.ping`; `POST /api/webhooks` and `PUT /api/webhooks/[id]` reject ghost values with 400; OpenAPI webhook description updated across 43 locales ([11050](https://github.com/diegosouzapw/OmniRoute/pull/11050)) diff --git a/changelog.d/fixes/11060-perplexity-filter.md b/changelog.d/fixes/11060-perplexity-filter.md deleted file mode 100644 index c221d3ccab..0000000000 --- a/changelog.d/fixes/11060-perplexity-filter.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): filter Perplexity model import to the Sonar family so Agent-API catalog ids stop surfacing as routable chat models (#11060) diff --git a/changelog.d/fixes/11085-claude-code-tool-name-casing.md b/changelog.d/fixes/11085-claude-code-tool-name-casing.md deleted file mode 100644 index 5ad424c141..0000000000 --- a/changelog.d/fixes/11085-claude-code-tool-name-casing.md +++ /dev/null @@ -1 +0,0 @@ -- **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 diff --git a/changelog.d/fixes/11089-chat-routing-synced-inventory.md b/changelog.d/fixes/11089-chat-routing-synced-inventory.md deleted file mode 100644 index 922b96a659..0000000000 --- a/changelog.d/fixes/11089-chat-routing-synced-inventory.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** filter chat connection selection by each connection's *synced* model inventory on multi-host self-hosted providers (`ollama-local`, `lm-studio`, `vllm`, …), so a request for a model only one host advertises is pinned to that host instead of failing over onto a host that never had it ([#11089](https://github.com/diegosouzapw/OmniRoute/issues/11089)) diff --git a/changelog.d/fixes/11095-termux-onnx.md b/changelog.d/fixes/11095-termux-onnx.md deleted file mode 100644 index 8c26803710..0000000000 --- a/changelog.d/fixes/11095-termux-onnx.md +++ /dev/null @@ -1 +0,0 @@ -- fix(install): make the ONNX dependency chain optional so Termux/Android installs succeed again (#11095) diff --git a/changelog.d/fixes/11101-reject-silent-validation.md b/changelog.d/fixes/11101-reject-silent-validation.md deleted file mode 100644 index 04b2a67d5a..0000000000 --- a/changelog.d/fixes/11101-reject-silent-validation.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/fixes/11102-combo-suggestion-count.md b/changelog.d/fixes/11102-combo-suggestion-count.md deleted file mode 100644 index 3cbf6f11d3..0000000000 --- a/changelog.d/fixes/11102-combo-suggestion-count.md +++ /dev/null @@ -1 +0,0 @@ -- **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=`) 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)). diff --git a/changelog.d/fixes/11103-persist-config-audit-log.md b/changelog.d/fixes/11103-persist-config-audit-log.md deleted file mode 100644 index aeb53b1781..0000000000 --- a/changelog.d/fixes/11103-persist-config-audit-log.md +++ /dev/null @@ -1 +0,0 @@ -- **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)). diff --git a/changelog.d/fixes/11109-stream-recovery-toolcall.md b/changelog.d/fixes/11109-stream-recovery-toolcall.md deleted file mode 100644 index 04a43382e4..0000000000 --- a/changelog.d/fixes/11109-stream-recovery-toolcall.md +++ /dev/null @@ -1 +0,0 @@ -- 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)) diff --git a/changelog.d/fixes/11116-reasoning-effort-capability-discovery.md b/changelog.d/fixes/11116-reasoning-effort-capability-discovery.md deleted file mode 100644 index fbc4dfe694..0000000000 --- a/changelog.d/fixes/11116-reasoning-effort-capability-discovery.md +++ /dev/null @@ -1 +0,0 @@ -- **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 diff --git a/changelog.d/fixes/11144-responses-parallel-tool-calls-index.md b/changelog.d/fixes/11144-responses-parallel-tool-calls-index.md deleted file mode 100644 index 35ba19b279..0000000000 --- a/changelog.d/fixes/11144-responses-parallel-tool-calls-index.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** parallel `function_call` items in a Responses API stream (e.g. several tool calls dispatched in the same turn) now each get a stable, distinct `index`/`id` when translated to Chat Completions streaming deltas, instead of colliding on index 0 and tripping strict stream parsers with `Expected 'id' to be a string.` ([#11144](https://github.com/diegosouzapw/OmniRoute/pull/11144)) diff --git a/changelog.d/fixes/11149-opencode-go-flat-rate.md b/changelog.d/fixes/11149-opencode-go-flat-rate.md deleted file mode 100644 index 7aa63ad455..0000000000 --- a/changelog.d/fixes/11149-opencode-go-flat-rate.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(analytics):** `opencode-go` is now classified as a flat-rate subscription, so cost analytics shows $0 for it instead of billing every call at the underlying model’s metered rate — it resells GLM, Kimi, Grok, DeepSeek, MiniMax, Qwen and GPT-5.x under one flat monthly fee, which made the overstatement large rather than marginal ([#11149](https://github.com/diegosouzapw/OmniRoute/pull/11149)) — thanks @electrumguy diff --git a/changelog.d/fixes/11154-provider-registry-node-net-bundle.md b/changelog.d/fixes/11154-provider-registry-node-net-bundle.md deleted file mode 100644 index b30d9e1392..0000000000 --- a/changelog.d/fixes/11154-provider-registry-node-net-bundle.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): keep `open-sse/config/providerRegistry.ts` free of `node:net` so the provider detail client bundle builds again — the host classification moved to a platform-free `src/shared/network/privateHost.ts` with a pure-JS `isIP` equivalent, leaving the #11122 routing behaviour unchanged (#11154) diff --git a/changelog.d/fixes/11162-combo-create-requires-model.md b/changelog.d/fixes/11162-combo-create-requires-model.md deleted file mode 100644 index 228e6a9b20..0000000000 --- a/changelog.d/fixes/11162-combo-create-requires-model.md +++ /dev/null @@ -1 +0,0 @@ -- **Combo create:** creating a routing combo without any model is now refused (`400`) — the CLI requires `--models`/`--model` on `combo create`, matching the dashboard which already rejected empty combos. diff --git a/changelog.d/fixes/11165-shared-registry-passthrough-model-lockout.md b/changelog.d/fixes/11165-shared-registry-passthrough-model-lockout.md deleted file mode 100644 index eabe67cb09..0000000000 --- a/changelog.d/fixes/11165-shared-registry-passthrough-model-lockout.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** a missing-model `404` on a provider that declares `passthroughModels: true` in the shared registry (novita, uncloseai, orcarouter and 37 others) now locks out only that model instead of cooling the entire connection — `hasPerModelQuota()` previously read only the open-sse registry and the local/self-hosted families ([#11165](https://github.com/diegosouzapw/OmniRoute/pull/11165)) — thanks @yourspraveen diff --git a/changelog.d/fixes/11180-keyless-custom-provider-auto-pool.md b/changelog.d/fixes/11180-keyless-custom-provider-auto-pool.md deleted file mode 100644 index c533feae54..0000000000 --- a/changelog.d/fixes/11180-keyless-custom-provider-auto-pool.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(routing):** a custom `openai-compatible-*` / `anthropic-compatible-*` connection pointing at a keyless self-hosted backend (llama.cpp, Ollama, vLLM started without an API key) now stays in the `auto/*` candidate pool instead of being silently dropped by the credential gate — for those IDs "no credential" is the normal configuration, not an unconfigured connection ([#11180](https://github.com/diegosouzapw/OmniRoute/pull/11180)) — thanks @marcs7 diff --git a/changelog.d/fixes/11181-lkgp-enabled-context.md b/changelog.d/fixes/11181-lkgp-enabled-context.md deleted file mode 100644 index d1c0cde5a3..0000000000 --- a/changelog.d/fixes/11181-lkgp-enabled-context.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(routing):** the Routing tab's "last known good provider" toggle now actually takes effect — `lkgpEnabled` was persisted and the `lkgp` strategy guarded on it, but the setting was never forwarded into the `RoutingContext` built in `resolveAutoStrategyOrder()`, so `context.lkgpEnabled` was always `undefined` and the off-switch was unreachable ([#11181](https://github.com/diegosouzapw/OmniRoute/issues/11181)) diff --git a/changelog.d/fixes/11271-ollama-capability-routing.md b/changelog.d/fixes/11271-ollama-capability-routing.md deleted file mode 100644 index 3846f4f0b9..0000000000 --- a/changelog.d/fixes/11271-ollama-capability-routing.md +++ /dev/null @@ -1 +0,0 @@ -- **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 diff --git a/changelog.d/fixes/11284-antigravity-empty-projectid-rejection.md b/changelog.d/fixes/11284-antigravity-empty-projectid-rejection.md deleted file mode 100644 index f86208d9a7..0000000000 --- a/changelog.d/fixes/11284-antigravity-empty-projectid-rejection.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** Antigravity OAuth marks connects with no Cloud Code projectId as degraded instead of a false "Connected"; BYOP detection at connect time, auto-disable of confirmed-missing accounts, and selection-side rotation ([#11284](https://github.com/diegosouzapw/OmniRoute/issues/11284)) diff --git a/changelog.d/fixes/11297-opencode-subagent-sessionid.md b/changelog.d/fixes/11297-opencode-subagent-sessionid.md deleted file mode 100644 index 37662d584e..0000000000 --- a/changelog.d/fixes/11297-opencode-subagent-sessionid.md +++ /dev/null @@ -1 +0,0 @@ -- **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 diff --git a/changelog.d/fixes/11311-group-model-pattern-regex-escape.md b/changelog.d/fixes/11311-group-model-pattern-regex-escape.md deleted file mode 100644 index dad1fa1e16..0000000000 --- a/changelog.d/fixes/11311-group-model-pattern-regex-escape.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/fixes/11319-upstream-proxy-host-spelling.md b/changelog.d/fixes/11319-upstream-proxy-host-spelling.md deleted file mode 100644 index a16ec17bba..0000000000 --- a/changelog.d/fixes/11319-upstream-proxy-host-spelling.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/fixes/11325-i18n-pt-placeholder-parity.md b/changelog.d/fixes/11325-i18n-pt-placeholder-parity.md deleted file mode 100644 index 97a2370955..0000000000 --- a/changelog.d/fixes/11325-i18n-pt-placeholder-parity.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/fixes/11326-kie-market-google-imagen-ids.md b/changelog.d/fixes/11326-kie-market-google-imagen-ids.md deleted file mode 100644 index 62dacb5d48..0000000000 --- a/changelog.d/fixes/11326-kie-market-google-imagen-ids.md +++ /dev/null @@ -1 +0,0 @@ -- **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)). diff --git a/changelog.d/fixes/11328-upstream-headers-proxy-auth.md b/changelog.d/fixes/11328-upstream-headers-proxy-auth.md deleted file mode 100644 index 2155b9ea90..0000000000 --- a/changelog.d/fixes/11328-upstream-headers-proxy-auth.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/fixes/11344-video-bridge-scene-aware-sampler.md b/changelog.d/fixes/11344-video-bridge-scene-aware-sampler.md deleted file mode 100644 index e33e40fab7..0000000000 --- a/changelog.d/fixes/11344-video-bridge-scene-aware-sampler.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(video-bridge):** fall back to the deterministic active-window midpoint when a one-frame scene-aware budget cannot preserve both timeline ends; a real FFmpeg fixture matrix now covers rapid cuts, gradual changes, static and short clips, and detector failure ([#11344](https://github.com/diegosouzapw/OmniRoute/pull/11344)). diff --git a/changelog.d/fixes/11347-codex-claude-empty-tool-use.md b/changelog.d/fixes/11347-codex-claude-empty-tool-use.md deleted file mode 100644 index 1c845d510f..0000000000 --- a/changelog.d/fixes/11347-codex-claude-empty-tool-use.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** Codex Responses tool calls translated for Claude clients no longer emit a duplicate `tool_use` block with the same ID and an empty name, preventing Claude Code from terminating with `No such tool available` ([#11347](https://github.com/diegosouzapw/OmniRoute/pull/11347)) diff --git a/changelog.d/fixes/11350-video-bridge-contact-sheet-labels.md b/changelog.d/fixes/11350-video-bridge-contact-sheet-labels.md deleted file mode 100644 index 5a4f4b2fba..0000000000 --- a/changelog.d/fixes/11350-video-bridge-contact-sheet-labels.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(video-bridge):** burn high-contrast timestamps into every bounded contact-sheet cell and add a real-model A/B harness whose promotion verdict stays `HOLD` until token, latency, and quality evidence is actually executed ([#11350](https://github.com/diegosouzapw/OmniRoute/pull/11350)) diff --git a/changelog.d/fixes/11362-video-bridge-result-cache.md b/changelog.d/fixes/11362-video-bridge-result-cache.md deleted file mode 100644 index 122d287aec..0000000000 --- a/changelog.d/fixes/11362-video-bridge-result-cache.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(video):** fingerprint protected Video Bridge bytes, coalesce concurrent work, and fail open when the bounded TTL/LRU result cache is unavailable or corrupt ([#11362](https://github.com/diegosouzapw/OmniRoute/pull/11362)) diff --git a/changelog.d/fixes/11367-catalog-eventloop-9147.md b/changelog.d/fixes/11367-catalog-eventloop-9147.md deleted file mode 100644 index 5f2efe48f8..0000000000 --- a/changelog.d/fixes/11367-catalog-eventloop-9147.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(catalog):** keep large `/v1/models` builds responsive by reusing the build-local capability snapshot throughout enrichment and Auto-Combo preparation, yielding cooperatively while constructing virtual candidate pools, and avoiding unrelated synchronous database diagnostics on the cache-TTL read path ([#11367](https://github.com/diegosouzapw/OmniRoute/pull/11367)) diff --git a/changelog.d/fixes/11382-video-bridge-dedup-policy.md b/changelog.d/fixes/11382-video-bridge-dedup-policy.md deleted file mode 100644 index e12d71ac4b..0000000000 --- a/changelog.d/fixes/11382-video-bridge-dedup-policy.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(video):** apply the caption-frame cap after bounded visual deduplication, preserve first/final candidates plus small high-contrast motion and text changes, and version the dedup policy in result-cache identity ([#11382](https://github.com/diegosouzapw/OmniRoute/pull/11382)). diff --git a/changelog.d/fixes/11388-live-ws-handshake-port.md b/changelog.d/fixes/11388-live-ws-handshake-port.md deleted file mode 100644 index f00f428b01..0000000000 --- a/changelog.d/fixes/11388-live-ws-handshake-port.md +++ /dev/null @@ -1 +0,0 @@ -- **Live dashboard:** honour the WebSocket port reported by `/api/v1/ws?handshake=1` instead of the port compiled into the bundle, so a `LIVE_WS_PORT` override reaches prebuilt Docker/npm images and Combo Studio Live connects behind a reverse proxy ([#11331](https://github.com/diegosouzapw/OmniRoute/issues/11331)). diff --git a/changelog.d/fixes/11394-modelsdev-interval-slider.md b/changelog.d/fixes/11394-modelsdev-interval-slider.md deleted file mode 100644 index 6f5e955c8e..0000000000 --- a/changelog.d/fixes/11394-modelsdev-interval-slider.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(dashboard):** Model Database sync interval slider ticks now match the thumb position — checkpoint-space slider with magnetic snap on release ([#11394](https://github.com/diegosouzapw/OmniRoute/pull/11394)) — thanks @An0nym0us92 diff --git a/changelog.d/fixes/7346-electron-hollow-nested-package-repair.md b/changelog.d/fixes/7346-electron-hollow-nested-package-repair.md deleted file mode 100644 index fd7e61988b..0000000000 --- a/changelog.d/fixes/7346-electron-hollow-nested-package-repair.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): repair hollow externalized package dirs in the nested `/node_modules` bundle location too, not just the top-level one, fixing macOS/Linux Electron `ERR_MODULE_NOT_FOUND` on Turbopack-externalized packages (#7346) diff --git a/changelog.d/fixes/7592-electron-cold-restart-native-driver-check.md b/changelog.d/fixes/7592-electron-cold-restart-native-driver-check.md deleted file mode 100644 index e6458879cf..0000000000 --- a/changelog.d/fixes/7592-electron-cold-restart-native-driver-check.md +++ /dev/null @@ -1 +0,0 @@ -- **Electron packaged smoke test:** add a cold-restart mode (`ELECTRON_SMOKE_COLD_RESTART=1`, wired blocking on the Linux release leg) that relaunches the packaged app against its own persisted `DATA_DIR` and asserts a native SQLite driver was selected instead of the sql.js WASM fallback, closing the regression-test gap flagged in the stale-ABI `better-sqlite3` investigation ([#7592](https://github.com/diegosouzapw/OmniRoute/issues/7592)). diff --git a/changelog.d/fixes/7764-quota-window-order.md b/changelog.d/fixes/7764-quota-window-order.md deleted file mode 100644 index 297131ed28..0000000000 --- a/changelog.d/fixes/7764-quota-window-order.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/fixes/8307-codex-image-account-fallback-retryable.md b/changelog.d/fixes/8307-codex-image-account-fallback-retryable.md deleted file mode 100644 index bd4a70a1ab..0000000000 --- a/changelog.d/fixes/8307-codex-image-account-fallback-retryable.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(images):** retry Codex image generation on a sibling ChatGPT account when the requested model isn't entitled on the current account, instead of failing the request outright ([#8307](https://github.com/diegosouzapw/OmniRoute/pull/8307)). diff --git a/changelog.d/fixes/8864-uncloseai-noauth.md b/changelog.d/fixes/8864-uncloseai-noauth.md deleted file mode 100644 index 8a38e6b836..0000000000 --- a/changelog.d/fixes/8864-uncloseai-noauth.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): treat UncloseAI as a no-auth provider so the connect form no longer forces a fake API key (#8864) diff --git a/changelog.d/fixes/9013-model-param-filter-save.md b/changelog.d/fixes/9013-model-param-filter-save.md deleted file mode 100644 index d81d7ab179..0000000000 --- a/changelog.d/fixes/9013-model-param-filter-save.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(dashboard):** model-level allowed/blocked param edits now persist when the compatibility popover is closed by clicking outside, and a failed save no longer clears the edit or reports success ([#9013](https://github.com/diegosouzapw/OmniRoute/pull/9013)) diff --git a/changelog.d/fixes/9123-search-provider-local-flag-guard-mismatch.md b/changelog.d/fixes/9123-search-provider-local-flag-guard-mismatch.md deleted file mode 100644 index bc51e12103..0000000000 --- a/changelog.d/fixes/9123-search-provider-local-flag-guard-mismatch.md +++ /dev/null @@ -1 +0,0 @@ -- fix(ssrf): make `getProviderOutboundGuard()` (used for search-provider connection validation, image generation and remote image fetch) honor the local-first default `OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS` the same way the chat validation guard already does, so a LAN-hosted SearXNG/Brave search provider works with only the LOCAL flag set instead of silently requiring `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` ([#9123](https://github.com/diegosouzapw/OmniRoute/issues/9123)). \ No newline at end of file diff --git a/changelog.d/fixes/9144-github-copilot-file-reference-compression-corruption.md b/changelog.d/fixes/9144-github-copilot-file-reference-compression-corruption.md deleted file mode 100644 index 6f48adeab5..0000000000 --- a/changelog.d/fixes/9144-github-copilot-file-reference-compression-corruption.md +++ /dev/null @@ -1 +0,0 @@ -- fix(compression): preserve unfenced raw code (e.g. Copilot #file references) from Caveman's prose recapitalization/whitespace cleanup, which was corrupting keyword casing and indentation (#9144) diff --git a/changelog.d/fixes/9147-catalog-eventloop-yield.md b/changelog.d/fixes/9147-catalog-eventloop-yield.md deleted file mode 100644 index 1f27c92b33..0000000000 --- a/changelog.d/fixes/9147-catalog-eventloop-yield.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): yield the event loop during catalog builds and bulk-load override/hidden-model tables (#9147) \ No newline at end of file diff --git a/changelog.d/fixes/9303-recovery-hint-all-targets-skipped.md b/changelog.d/fixes/9303-recovery-hint-all-targets-skipped.md deleted file mode 100644 index 78649d651f..0000000000 --- a/changelog.d/fixes/9303-recovery-hint-all-targets-skipped.md +++ /dev/null @@ -1 +0,0 @@ -- fix(combo): recovery hint for all_targets_skipped now points at provider quota/availability instead of 'transient, just retry' (#9303) diff --git a/changelog.d/fixes/9617-gemini-uniqueitems-strip.md b/changelog.d/fixes/9617-gemini-uniqueitems-strip.md deleted file mode 100644 index 8e01e17a28..0000000000 --- a/changelog.d/fixes/9617-gemini-uniqueitems-strip.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): strip uniqueItems from Gemini tool schemas (Gemini rejects it with 400 'Unknown name uniqueItems') (#9617) diff --git a/changelog.d/fixes/9692-openai-to-claude-tool-images.md b/changelog.d/fixes/9692-openai-to-claude-tool-images.md deleted file mode 100644 index c082d0dbc3..0000000000 --- a/changelog.d/fixes/9692-openai-to-claude-tool-images.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** convert OpenAI `image_url` blocks nested in `role: "tool"` / `tool_result` content to Claude `image` source blocks so OpenAI-compatible clients (Kimi Code CLI `ReadMediaFile`, and any other tool that returns media) no longer 400 the next Claude-format upstream turn ([#9692](https://github.com/diegosouzapw/OmniRoute/issues/9692)) diff --git a/changelog.d/fixes/9708-codex-same-account-retry.md b/changelog.d/fixes/9708-codex-same-account-retry.md deleted file mode 100644 index 2ccb7fb97f..0000000000 --- a/changelog.d/fixes/9708-codex-same-account-retry.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** retry a retryable Codex pre-output 502/503/504/507 once on the same account (2–3s jitter) before cooling the connection, and stop translating that mixed pool into an all-accounts quota `429` ([#9708](https://github.com/diegosouzapw/OmniRoute/issues/9708)) diff --git a/changelog.d/fixes/9763-ratelimit-mintime-floor.md b/changelog.d/fixes/9763-ratelimit-mintime-floor.md deleted file mode 100644 index 2b145f1e1a..0000000000 --- a/changelog.d/fixes/9763-ratelimit-mintime-floor.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(ratelimit):** respect operator `minTimeBetweenRequestsMs` floor when relaxing the limiter on headroom — the adaptive rate-limit learning no longer silently erases a configured minimum gap between requests when the upstream reports plenty of remaining capacity ([#9763](https://github.com/diegosouzapw/OmniRoute/issues/9763)). diff --git a/changelog.d/fixes/9821-mcp-pack-unit-stall.md b/changelog.d/fixes/9821-mcp-pack-unit-stall.md deleted file mode 100644 index c8f677535b..0000000000 --- a/changelog.d/fixes/9821-mcp-pack-unit-stall.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(test):** remove live `npm pack` from MCP files unit test (it stalled concurrent `test:unit` via prepare→husky + monorepo pack walk); keep the static #3578 `files` allowlist + negation guards in unit and fold #3821 pack assertions into `check:pack-artifact` / `check:pack-policy` (already `--ignore-scripts`). diff --git a/changelog.d/fixes/9935-media-playground-masked-bearer.md b/changelog.d/fixes/9935-media-playground-masked-bearer.md deleted file mode 100644 index 2fd123d801..0000000000 --- a/changelog.d/fixes/9935-media-playground-masked-bearer.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): media mini-playgrounds authenticate via session instead of sending the masked API key as Bearer, fixing 401s under REQUIRE_API_KEY (#9935) diff --git a/changelog.d/fixes/9970-credential-health-search-provider-exclusion.md b/changelog.d/fixes/9970-credential-health-search-provider-exclusion.md deleted file mode 100644 index 04aef65204..0000000000 --- a/changelog.d/fixes/9970-credential-health-search-provider-exclusion.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): exclude search providers from credential-health scheduler sweep to stop burning billed API queries (#9970) diff --git a/changelog.d/fixes/PENDING-electron-window-hidden-hostname-bind.md b/changelog.d/fixes/PENDING-electron-window-hidden-hostname-bind.md deleted file mode 100644 index 6a88ba926a..0000000000 --- a/changelog.d/fixes/PENDING-electron-window-hidden-hostname-bind.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(electron):** desktop window stays hidden on Windows because the embedded Next.js server binds to the machine hostname instead of loopback ([#PENDING](https://github.com/diegosouzapw/OmniRoute/pull/PENDING)) diff --git a/changelog.d/fixes/api-manager-empty-combo-allowlist.md b/changelog.d/fixes/api-manager-empty-combo-allowlist.md deleted file mode 100644 index 7180578281..0000000000 --- a/changelog.d/fixes/api-manager-empty-combo-allowlist.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api-manager):** Allowed Combos can now be restricted to zero entries: **All** is stored explicitly as `combo/*`, while **Restrict** with no selection saves an empty allowlist that denies Combo routes without blocking direct models. Existing keys are migrated to preserve their previous allow-all behavior. diff --git a/changelog.d/fixes/assemble-standalone-cpsync-race.md b/changelog.d/fixes/assemble-standalone-cpsync-race.md deleted file mode 100644 index 82fabbcad6..0000000000 --- a/changelog.d/fixes/assemble-standalone-cpsync-race.md +++ /dev/null @@ -1 +0,0 @@ -- fix(build): tolerate a same-realpath symlink or stale-typed dest in the standalone bundle assembler, fixing non-deterministic `ERR_FS_CP_EINVAL`/`ERR_FS_CP_DIR_TO_NON_DIR` crashes under heavy concurrent build I/O diff --git a/changelog.d/fixes/auto-empty-pool-log-once.md b/changelog.d/fixes/auto-empty-pool-log-once.md deleted file mode 100644 index 90d92ed82f..0000000000 --- a/changelog.d/fixes/auto-empty-pool-log-once.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(auto):** rate-limit `auto/ matched no connected models` warnings to once per minute per label (`open-sse/services/autoCombo/virtualFactory.ts`) diff --git a/changelog.d/fixes/basered-deadcode-opencode-config-dir.md b/changelog.d/fixes/basered-deadcode-opencode-config-dir.md deleted file mode 100644 index 0055420d4f..0000000000 --- a/changelog.d/fixes/basered-deadcode-opencode-config-dir.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): drop the orphaned `resolveOpencodeConfigDir` re-export from `cliRuntime` — it lost its last consumer in #10246 and diverged from the canonical resolver by one directory level (#9985) diff --git a/changelog.d/fixes/build-advisory-hosted-runner.md b/changelog.d/fixes/build-advisory-hosted-runner.md deleted file mode 100644 index 4bc5ef5469..0000000000 --- a/changelog.d/fixes/build-advisory-hosted-runner.md +++ /dev/null @@ -1 +0,0 @@ -- fix(ci): make `Build (advisory)` produce a signal again — pinned to a hosted runner with the swap/heap provisioning `Fast Production Build` proves sufficient, and scoped to fork PRs, which are the only ones `build.yml` cannot cover (72 of the last 100 PRs into `release/**`) diff --git a/changelog.d/fixes/catalog-cache-hash-apikey.md b/changelog.d/fixes/catalog-cache-hash-apikey.md deleted file mode 100644 index e815ab1fec..0000000000 --- a/changelog.d/fixes/catalog-cache-hash-apikey.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** hash API keys in the `/v1/models` catalog cache Map key so heap dumps cannot leak bearer tokens (`src/app/api/v1/models/catalogCache.ts`) diff --git a/changelog.d/fixes/catalog-openrouter-gemini-embedding-2.md b/changelog.d/fixes/catalog-openrouter-gemini-embedding-2.md deleted file mode 100644 index 21fd9808e3..0000000000 --- a/changelog.d/fixes/catalog-openrouter-gemini-embedding-2.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** register live OpenRouter Gemini Embedding 2 ids (`google/gemini-embedding-2` and `google/gemini-embedding-2-preview`, 3072-d) in the curated embeddings catalog so `GET /v1/models` and `GET /v1/embeddings` list the ids that already serve — thanks @RaviTharuma diff --git a/changelog.d/fixes/claude-to-gemini-consecutive-roles.md b/changelog.d/fixes/claude-to-gemini-consecutive-roles.md deleted file mode 100644 index 17483dce52..0000000000 --- a/changelog.d/fixes/claude-to-gemini-consecutive-roles.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** merge consecutive same-role contents in direct Claude to Gemini request translation to prevent upstream HTTP 400 errors diff --git a/changelog.d/fixes/cli-update-npm-win32-11335.md b/changelog.d/fixes/cli-update-npm-win32-11335.md deleted file mode 100644 index fae14f20a9..0000000000 --- a/changelog.d/fixes/cli-update-npm-win32-11335.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** `omniroute update` now finds npm on Windows. It called `execFile("npm", …)` with no shell, and on Node ≥ 24 a `.cmd` wrapper cannot be spawned that way (nodejs/node#52554) — while a bare `npm` can also resolve to an extensionless shim `CreateProcess` refuses. The result was `✖ Could not check latest version. Is npm available?` in a terminal where `npm view omniroute version` worked fine, so the updater was unusable on Windows even though nothing was wrong with the install. This is the same class as #5379/#5542, which fixed the server-side calls; the CLI entry points were missed because they are plain `.mjs` and cannot import the TypeScript helper. `bin/cli/npm-exec.mjs` now states the same rule for them: `npm.cmd` plus a shell on win32, no shell anywhere else. Both npm lookups in `update.mjs` (version and changelog) pass a literal argv array, so enabling the shell cannot splice a runtime value into the command line — a test asserts that and fails if a future edit interpolates one. (#11335) diff --git a/changelog.d/fixes/cline-task-id-passthrough.md b/changelog.d/fixes/cline-task-id-passthrough.md deleted file mode 100644 index a6d2ecec57..0000000000 --- a/changelog.d/fixes/cline-task-id-passthrough.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cline):** Preserve client-supplied Cline task IDs and omit the header when clients provide none, preventing request-scoped proxy IDs from being reported as tasks. diff --git a/changelog.d/fixes/codex-appserver-hardening.md b/changelog.d/fixes/codex-appserver-hardening.md deleted file mode 100644 index b73bc3fc20..0000000000 --- a/changelog.d/fixes/codex-appserver-hardening.md +++ /dev/null @@ -1 +0,0 @@ -- 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. diff --git a/changelog.d/fixes/codex-max-context-window.md b/changelog.d/fixes/codex-max-context-window.md deleted file mode 100644 index 391d894e46..0000000000 --- a/changelog.d/fixes/codex-max-context-window.md +++ /dev/null @@ -1 +0,0 @@ -- 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 diff --git a/changelog.d/fixes/combo-connection-scoped-reasoning-efforts.md b/changelog.d/fixes/combo-connection-scoped-reasoning-efforts.md deleted file mode 100644 index 3a53f1323a..0000000000 --- a/changelog.d/fixes/combo-connection-scoped-reasoning-efforts.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(catalog):** derive combo reasoning-effort tiers from the exact runtime-selectable connection scope, intersecting dynamic, pinned, allowlisted, and compatible provider-node evidence while failing closed on unknown capabilities. diff --git a/changelog.d/fixes/combo-sticky-pin-clear-on-disable.md b/changelog.d/fixes/combo-sticky-pin-clear-on-disable.md deleted file mode 100644 index 17abffb7f7..0000000000 --- a/changelog.d/fixes/combo-sticky-pin-clear-on-disable.md +++ /dev/null @@ -1 +0,0 @@ -- fix(combo): evict in-memory session-stickiness bindings when a combo disables stickiness, so stale pins stop overriding the declared priority order until TTL/restart diff --git a/changelog.d/fixes/command-code-effort-capabilities.md b/changelog.d/fixes/command-code-effort-capabilities.md deleted file mode 100644 index 38057107ef..0000000000 --- a/changelog.d/fixes/command-code-effort-capabilities.md +++ /dev/null @@ -1 +0,0 @@ -- fix(combo): resolve effort-suffixed command-code variants (e.g. `deepseek-v4-flash-max`) to their base model for capability lookups, so tool-bearing combo requests keep the declared priority order instead of reordering behind models with confirmed capabilities diff --git a/changelog.d/fixes/compression-run-telemetry-retention-ms.md b/changelog.d/fixes/compression-run-telemetry-retention-ms.md deleted file mode 100644 index cbaedbe25e..0000000000 --- a/changelog.d/fixes/compression-run-telemetry-retention-ms.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(db):** the `compression_run_telemetry` retention sweep now actually deletes expired rows. Its cutoff was computed in epoch seconds while the column stores epoch milliseconds, so `WHERE timestamp < cutoff` never matched and the table added by #6848 to bound `storage.sqlite` growth was unbounded in practice. Same unit mismatch as #9625, which corrected the sibling `domain_cost_history` sweep and missed this call site diff --git a/changelog.d/fixes/compression-worker-bundler-resolve.md b/changelog.d/fixes/compression-worker-bundler-resolve.md deleted file mode 100644 index 3a867303d6..0000000000 --- a/changelog.d/fixes/compression-worker-bundler-resolve.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(compression):** use `pathToFileURL` in `compressionWorkerPool` so bundlers (Webpack / Turbopack) do not attempt static asset resolution of missing `compressionWorker.js` during build diff --git a/changelog.d/fixes/dbstat-optional-vtab.md b/changelog.d/fixes/dbstat-optional-vtab.md deleted file mode 100644 index 5d56e93d1a..0000000000 --- a/changelog.d/fixes/dbstat-optional-vtab.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(db):** database settings API no longer returns HTTP 500 on SQLite builds compiled without the optional `dbstat` virtual table (sql.js/WASM); per-table sizes degrade to 0 instead of failing the whole stats call diff --git a/changelog.d/fixes/discovery-metadata-effort-tiers.md b/changelog.d/fixes/discovery-metadata-effort-tiers.md deleted file mode 100644 index 3744a2063f..0000000000 --- a/changelog.d/fixes/discovery-metadata-effort-tiers.md +++ /dev/null @@ -1 +0,0 @@ -- fix(discovery): parse upstream reasoning tiers nested under metadata.reasoning.supported_efforts (neuralwatt /v1/models shape) so synced openai-compatible models advertise effort aliases diff --git a/changelog.d/fixes/docker-healthcheck-use-healthz.md b/changelog.d/fixes/docker-healthcheck-use-healthz.md deleted file mode 100644 index a139e2dd4c..0000000000 --- a/changelog.d/fixes/docker-healthcheck-use-healthz.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(ops):** Docker HEALTHCHECK probes lightweight `/healthz` instead of `/api/monitoring/health` so a busy event loop does not mark the container Unhealthy (`scripts/dev/healthcheck.mjs`) diff --git a/changelog.d/fixes/embed-gemini-missing-creds-hint.md b/changelog.d/fixes/embed-gemini-missing-creds-hint.md deleted file mode 100644 index 41b61713f7..0000000000 --- a/changelog.d/fixes/embed-gemini-missing-creds-hint.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** `/v1/embeddings` 400s for native `gemini-embedding-2` now name the working OpenRouter ids (`openrouter/google/gemini-embedding-2` and the preview alias) instead of only `No credentials for embedding provider: gemini` — thanks @RaviTharuma diff --git a/changelog.d/fixes/forward-codex-quota-headers.md b/changelog.d/fixes/forward-codex-quota-headers.md deleted file mode 100644 index 86aa1e7df4..0000000000 --- a/changelog.d/fixes/forward-codex-quota-headers.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** keep Codex/Anthropic quota headers under the upstream forwarding budget; drop `x-codex-turn-state` and raise the 768-byte cap (`open-sse/handlers/chatCore/responseHeaders.ts`) diff --git a/changelog.d/fixes/glm-credit-limit-quota.md b/changelog.d/fixes/glm-credit-limit-quota.md deleted file mode 100644 index e46eb96ee9..0000000000 --- a/changelog.d/fixes/glm-credit-limit-quota.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(usage):** z.ai/GLM coding-plan subscription keys now render their quota cards again, with absolute credits. Z.ai's `/api/monitor/usage/quota/limit` switched these keys from `TOKENS_LIMIT` to `CREDIT_LIMIT` rows (same `unit`/`number` semantics: unit=3/number=5 → 5-hour window, unit=6/number=1 → weekly), and the parser only matched `TOKENS_LIMIT`/`TIME_LIMIT`, so both rows were dropped and the subscription card rendered empty. `CREDIT_LIMIT` is now accepted alongside `TOKENS_LIMIT`, and when the row carries absolute credit fields (`usage`/`currentValue`/`remaining`) they are preferred over the percent-only scale, so the card shows `3341 / 28000` like z.ai's own dashboard instead of `11 / 100` diff --git a/changelog.d/fixes/lasterror-provider-error-detail.md b/changelog.d/fixes/lasterror-provider-error-detail.md deleted file mode 100644 index 60872c52cc..0000000000 --- a/changelog.d/fixes/lasterror-provider-error-detail.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(auth):** a connection's `lastError` now names the real upstream failure instead of the bare string `Provider error`. `markAccountUnavailable` kept the reason only when it was already a string, so every other shape collapsed to that literal — and the shape that matters most is not a string: a failed `fetch` arrives as `TypeError: fetch failed` with the actionable part on `error.cause.code`, which means a wrong port, a firewall, a DNS failure and a blocked proxy all looked identical in the dashboard and in the console line. `describeUpstreamFailure` (in `src/shared/utils/upstreamError.ts`, reusing the `extractErrorMessage` that already parsed provider bodies) reads Error messages and appends the transport code when the message does not already carry it, reads the usual provider JSON shapes (`error.message`, `message`, string `error`, `detail`, `errors[]`), and falls back to the code alone before giving up. It never serializes the error object wholesale, so a request body or header attached to an error cannot leak into the stored reason — pinned by a test. diff --git a/changelog.d/fixes/live-ws-public-url-runtime.md b/changelog.d/fixes/live-ws-public-url-runtime.md deleted file mode 100644 index a46a9798f8..0000000000 --- a/changelog.d/fixes/live-ws-public-url-runtime.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(live-ws):** the Live dashboard socket can now be pointed at a reverse proxy without rebuilding the image. `NEXT_PUBLIC_*` is inlined at BUILD time, so a prebuilt Docker or npm image never carries an operator's `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL` — which is exactly why the browser discovers the socket through `/api/v1/ws?handshake=1` instead. The server side of that handshake, however, read only the `NEXT_PUBLIC_`-prefixed name, so it had nothing to echo: behind Traefik the dashboard kept dialling `wss://:20132/live-ws` and sat on "Live disabled — WebSocket disconnected. Showing last known state." `LIVE_WS_PUBLIC_URL` is now read at runtime alongside the existing `LIVE_WS_HOST` / `LIVE_WS_PORT`, and the prefixed name stays supported as the fallback, so deployments that already set it are unaffected. Only `ws://` and `wss://` values are accepted, matching the guard the client already applies. (#11331) diff --git a/changelog.d/fixes/minimax-music-generation-dispatch.md b/changelog.d/fixes/minimax-music-generation-dispatch.md deleted file mode 100644 index e0cf2114ca..0000000000 --- a/changelog.d/fixes/minimax-music-generation-dispatch.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** MiniMax music models now generate audio instead of failing with `Unsupported music format: minimax-music` — the provider entry was registered in the music registry (and advertised by `/v1/models`), but `handleMusicGeneration` had no branch for its format, so every `minimax/*` music request fell through the dispatch chain to a 400. Adds the missing dispatch: a single synchronous POST with the `base_resp` envelope check (a non-zero `status_code` arrives on HTTP 200 too), `data.status` handling (an unfinished generation is reported instead of polled — the operation has no task id and no query endpoint), `url` and `hex` output formats (hex normalized to base64), `mp3`/`wav`/`pcm` containers via `audio_setting`, and the regional endpoint through the per-connection base-URL override, which is also the only host that accepts `aigc_watermark`. The registry entry gains the generation and cover model ids it was missing and drops a query URL that does not exist for this operation. Regression guard: `tests/unit/minimax-music-generation.test.ts` (9 tests). diff --git a/changelog.d/fixes/models-dev-sync-env-killswitch.md b/changelog.d/fixes/models-dev-sync-env-killswitch.md deleted file mode 100644 index 0724f52356..0000000000 --- a/changelog.d/fixes/models-dev-sync-env-killswitch.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(models):** honor `MODELS_DEV_SYNC_ENABLED=0` as a hard kill switch over the dashboard setting so a wedged `/healthz` / UI can be recovered without HTTP (`src/lib/modelsDevSync.ts`) diff --git a/changelog.d/fixes/opencode-force-cli-ua.md b/changelog.d/fixes/opencode-force-cli-ua.md deleted file mode 100644 index f8a194a90b..0000000000 --- a/changelog.d/fixes/opencode-force-cli-ua.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** when `OPENCODE_SYNTHESIZE_CLI_HEADERS=true`, a non-CLI client User-Agent (e.g. `curl/8.5.0`, SDKs) on opencode-go/opencode-zen/opencode-free requests is now REPLACED with the synthesized `opencode-cli/1.0.0` instead of being honored — opencode.ai's free tier (`/zen/v1`) returns `FreeUsageLimitError` 429 for generic client UAs egressing from datacenter IPs, which made the #5997 CLI-identity synthesis ineffective for non-CLI clients. Client UAs already matching `opencode-cli/…` are preserved (the real CLI's versioned identity stays intact); all other client-supplied `x-opencode-*` headers keep client-wins. Regression guard: `tests/unit/opencode-cli-headers-synthesis-5997.test.ts` (7, incl. non-CLI UA replaced + CLI UA preserved). (#5997 follow-up) diff --git a/changelog.d/fixes/opencode-merge-provider-guard.md b/changelog.d/fixes/opencode-merge-provider-guard.md deleted file mode 100644 index aa1f02e63b..0000000000 --- a/changelog.d/fixes/opencode-merge-provider-guard.md +++ /dev/null @@ -1 +0,0 @@ -- **OpenCode config merge:** stop `mergeOpenCodeConfig` splaying a malformed `provider` block into index keys. The root was already guarded against a non-object; the `provider` branch it spreads one level down was not, so an existing `"provider": ["a", "b"]` merged to `{"0": "a", "1": "b", …}`. Its sibling `mergeOpenCodeConfigText` already refuses the same input. diff --git a/changelog.d/fixes/openrouter-synced-model-context-window-and-default-effort.md b/changelog.d/fixes/openrouter-synced-model-context-window-and-default-effort.md deleted file mode 100644 index b26e1c2086..0000000000 --- a/changelog.d/fixes/openrouter-synced-model-context-window-and-default-effort.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(models):** a model synced from a provider's own `/models` discovery is now enforced at its real context window immediately, instead of waiting up to 24h for the Feature 5004 reconciler's next tick. The request-time token-limit chain resolves the window from `auto:discovery` overrides, which previously were only written at startup and on a 24h interval — so any model synced mid-cycle (models.dev not indexing it yet, no static registry entry) fell through to the provider's static `defaultContextLength` (128K for OpenRouter) while `/v1/models` simultaneously advertised the real window from the same discovery data. Measured: `openrouter/stealth/ox-alpha` advertised `context_length: 1048576` but rejected requests over 128K with `context_length_exceeded` for a full day after its sync. The reconcile now also runs opportunistically (debounced, fire-and-forget) right after a synced catalog write changes. Companion fix: discovery now captures the vendor-declared `reasoning.default_effort` (e.g. OpenRouter `stealth/ox-alpha` declares `max`, normalized to `xhigh`) as `defaultThinkingEffort`, and the OpenAI dispatch path injects it when a request carries no reasoning field of any shape — the lowest-priority default behind a `-{effort}` suffix alias and a static `ModelSpec.defaultReasoningEffort` — so a reasoning model that returns an empty response without an explicit effort gets the vendor default instead of `upstream_empty_response`. diff --git a/changelog.d/fixes/pending-cc-cache-control-ttl-default.md b/changelog.d/fixes/pending-cc-cache-control-ttl-default.md deleted file mode 100644 index 0d89bee475..0000000000 --- a/changelog.d/fixes/pending-cc-cache-control-ttl-default.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** Claude Code / CC-protocol-compatible clients sending `cache_control` with no `ttl` on the native Claude OAuth path (`claude`/`cc`) now default to the 1h extended cache TTL instead of silently falling back to Anthropic's 5-minute default, even though the 1h beta is always negotiated on this path — thanks @jeff-alves diff --git a/changelog.d/fixes/pending-opencode-empty-rejection-rotation.md b/changelog.d/fixes/pending-opencode-empty-rejection-rotation.md deleted file mode 100644 index 82a88c5905..0000000000 --- a/changelog.d/fixes/pending-opencode-empty-rejection-rotation.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(executors):** OpencodeExecutor rotates (or retries once on a single-account direct path) on upstream 400 empty-body rejections — malformed completion envelopes with no error field were propagated as success and killed client sessions. Bounded +1 attempt per request; body reads are conditioned on status 400 so successful/streaming responses are never buffered. 400s carrying an error field keep propagating immediately. diff --git a/changelog.d/fixes/pending-opencode-jsonc-config.md b/changelog.d/fixes/pending-opencode-jsonc-config.md deleted file mode 100644 index 0951ae78f2..0000000000 --- a/changelog.d/fixes/pending-opencode-jsonc-config.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** recognize native `opencode.jsonc` files in OpenCode detection, generated-provider setup, and dashboard save/apply flows; preserve unrelated JSONC comments and provider settings, write updates back to the selected file, and refuse to overwrite invalid config ([#10227](https://github.com/diegosouzapw/OmniRoute/issues/10227)) — thanks @tito13kfm diff --git a/changelog.d/fixes/release-v3850-basereds-tests-i18n.md b/changelog.d/fixes/release-v3850-basereds-tests-i18n.md deleted file mode 100644 index 3a6dee61b9..0000000000 --- a/changelog.d/fixes/release-v3850-basereds-tests-i18n.md +++ /dev/null @@ -1 +0,0 @@ -- fix(i18n): complete Vietnamese translations for recently added UI strings (#9985) diff --git a/changelog.d/fixes/release-v3850-basereds.md b/changelog.d/fixes/release-v3850-basereds.md deleted file mode 100644 index 30444ba706..0000000000 --- a/changelog.d/fixes/release-v3850-basereds.md +++ /dev/null @@ -1,3 +0,0 @@ -- fix(api): repair broken `@/lib/db/connections` import in the usage utilization route that failed the production build (#10939 follow-up) -- chore(docs): regenerate PROVIDER_REFERENCE and refresh README diagram SVGs to the real provider count (347) -- chore(lint): prune ESLint suppressions orphaned on the release branch diff --git a/changelog.d/fixes/release-v3850-turbopack-build-red.md b/changelog.d/fixes/release-v3850-turbopack-build-red.md deleted file mode 100644 index 44f69203e3..0000000000 --- a/changelog.d/fixes/release-v3850-turbopack-build-red.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(build):** repair the broken Turbopack production build, the red lint gate and a runtime crash on `release/v3.8.50`. Six independent module-level defects, each from a different PR, had accumulated because the `Build` CI job is advisory rather than blocking: a lost closing brace in `modelSelectModalHelpers.ts` that swallowed `PROVIDER_TEST_CHUNK_SIZE` into a function body (#9011); `handleFalVideoGeneration` imported twice in `videoGeneration.ts` after the provider-neutral Fal module superseded the standalone handler (#9982 over #9969); `catalog.ts` still re-exporting and calling the injectable stale-while-revalidate policy that #9199 deliberately replaced with a fixed 30 s bound when it landed on top of #8728 — the consumer and the #8728 test suite were never realigned; two dangling statements left in `catalogCache.ts::scheduleBackgroundRefresh` referencing undeclared `inFlight`/`promise`, which made **every** stale-while-revalidate read throw a `ReferenceError` at runtime (a defect the build never caught, surfaced here by the realigned test); a generated wasm-bindgen sidecar URL in `tinycmsSigner.ts` that Turbopack resolves at build time even though the WASM module ships inlined as base64 (#8736/#10087); `conolDiscovery.ts` importing `getProviderOutboundGuard` from `outboundUrlGuard` instead of the sibling `outboundUrlGuardPolicy` module that actually exports it (#8974) — fixed on the consumer side, since re-exporting it would put a `@/`-aliased import into the module the packaged CLI loads without a tsconfig (#7682); and an unbalanced brace in `tests/unit/db-adapters/driverFactory.test.ts` where a new case was inserted between the preceding test's `finally` block and its `});`, so the whole file stopped parsing and the SQLite driver-cascade coverage silently stopped running since 2026-08-11 (#9173). diff --git a/changelog.d/fixes/secret-leak-error-surface-hardening.md b/changelog.d/fixes/secret-leak-error-surface-hardening.md deleted file mode 100644 index ed2e4474a0..0000000000 --- a/changelog.d/fixes/secret-leak-error-surface-hardening.md +++ /dev/null @@ -1 +0,0 @@ -- **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. diff --git a/changelog.d/fixes/sqljs-atomic-persist.md b/changelog.d/fixes/sqljs-atomic-persist.md deleted file mode 100644 index db50495f4d..0000000000 --- a/changelog.d/fixes/sqljs-atomic-persist.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(db):** the sql.js fallback now publishes the database atomically — temp file in the same directory, `fsync`, then `rename()` — instead of rewriting it in place with `writeFileSync`. sql.js has no incremental write path, so every save rewrote the whole image through an `O_TRUNC` open: for the duration of the write the on-disk database was 0 bytes and then partial, a window that scales with database size and recurs on every save. Unlike better-sqlite3 / node:sqlite, that window is not covered by SQLite's locking protocol, so it was visible to every OTHER process reading the same file (a backup job, a metrics exporter, an operator running `sqlite3`), which got `SQLITE_CORRUPT` — "database disk image is malformed" — while `PRAGMA integrity_check` passed moments later. It also closes a total-loss window: a crash mid-write used to leave the real database truncated, and now only leaves a stale temp file diff --git a/changelog.d/maintenance/10297-k8s-probe-recommendations.md b/changelog.d/maintenance/10297-k8s-probe-recommendations.md deleted file mode 100644 index adc9d4491e..0000000000 --- a/changelog.d/maintenance/10297-k8s-probe-recommendations.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(ops):** document Kubernetes probe recommendations — TCP (or soft HTTP) liveness, HTTP `/healthz` readiness, avoid `/api/monitoring/health` as kubelet liveness ([#10297](https://github.com/diegosouzapw/OmniRoute/pull/10297)) — thanks @RaviTharuma diff --git a/changelog.d/maintenance/10317-latest-tracks-highest-stable.md b/changelog.d/maintenance/10317-latest-tracks-highest-stable.md deleted file mode 100644 index 9fdb4d2c81..0000000000 --- a/changelog.d/maintenance/10317-latest-tracks-highest-stable.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(docker):** spell out that `:latest` tracks the highest **published** stable SemVer (not git `main`), and that GitOps should pin `X.Y.Z` ([#10317](https://github.com/diegosouzapw/OmniRoute/issues/10317)) diff --git a/changelog.d/maintenance/10349-optional-work-event-loop.md b/changelog.d/maintenance/10349-optional-work-event-loop.md deleted file mode 100644 index 0cd695e4a7..0000000000 --- a/changelog.d/maintenance/10349-optional-work-event-loop.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(backend):** document that memory extraction, skills injection, and token refresh share the request event loop, plus dashboard kill switches ([#10349](https://github.com/diegosouzapw/OmniRoute/issues/10349)) diff --git a/changelog.d/maintenance/10350-sqlite-single-replica-ha.md b/changelog.d/maintenance/10350-sqlite-single-replica-ha.md deleted file mode 100644 index 9b158d5787..0000000000 --- a/changelog.d/maintenance/10350-sqlite-single-replica-ha.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(docker):** document default SQLite as single-replica / HA-unsupported, including Recreate and HEALTHCHECK session blast radius ([#10350](https://github.com/diegosouzapw/OmniRoute/issues/10350)) diff --git a/changelog.d/maintenance/10351-pre-write-backup-throttle.md b/changelog.d/maintenance/10351-pre-write-backup-throttle.md deleted file mode 100644 index f6141d30ea..0000000000 --- a/changelog.d/maintenance/10351-pre-write-backup-throttle.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(backend):** document that pre-write SQLite backups (including models.dev pricing) are throttled to once per 60 minutes and can be disabled with `DISABLE_SQLITE_AUTO_BACKUP` ([#10351](https://github.com/diegosouzapw/OmniRoute/issues/10351)) diff --git a/changelog.d/maintenance/10704-basereds-sse-comments-vi-parity.md b/changelog.d/maintenance/10704-basereds-sse-comments-vi-parity.md deleted file mode 100644 index e2874a2be4..0000000000 --- a/changelog.d/maintenance/10704-basereds-sse-comments-vi-parity.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(tests):** drain three base-reds on the release branch — the Vietnamese locale regained parity with English (6 keys added), the chatCore SSE test now asserts the comment-free default that #10539 introduced instead of the trailer it replaced, and the Antigravity cloudcode test asserts the missing-messages guard it is named for instead of a `/ok/` regex that only ever matched the "ok" inside `: x-omniroute-tokens-in` ([#10704](https://github.com/diegosouzapw/OmniRoute/pull/10704)) diff --git a/changelog.d/maintenance/10775-remove-dead-enforce-secrets.md b/changelog.d/maintenance/10775-remove-dead-enforce-secrets.md deleted file mode 100644 index 4f44473360..0000000000 --- a/changelog.d/maintenance/10775-remove-dead-enforce-secrets.md +++ /dev/null @@ -1 +0,0 @@ -- chore(security): remove the unused `enforceSecrets()` duplicate of the boot secret check and pin the live `enforceWebRuntimeEnv()` wiring with a regression test (#10775) diff --git a/changelog.d/maintenance/10778-grokbuild-suppression-fix.md b/changelog.d/maintenance/10778-grokbuild-suppression-fix.md deleted file mode 100644 index 15c5df7ef7..0000000000 --- a/changelog.d/maintenance/10778-grokbuild-suppression-fix.md +++ /dev/null @@ -1 +0,0 @@ -- fix(quality): register GrokBuildToolCard.tsx react-hooks/set-state-in-effect suppression (dropped in #10778's uncommitted fix) diff --git a/changelog.d/maintenance/10779-combo-invocation-docs.md b/changelog.d/maintenance/10779-combo-invocation-docs.md deleted file mode 100644 index 00138a3a65..0000000000 --- a/changelog.d/maintenance/10779-combo-invocation-docs.md +++ /dev/null @@ -1 +0,0 @@ -- **docs:** Custom combos are only invoked by their exact name in the `model` field — `auto` remains a separate zero-config router, and `openrouter/auto` is a paid OpenRouter product, not an alias ([#10779](https://github.com/diegosouzapw/OmniRoute/pull/10779)) — thanks @maxmad64bis diff --git a/changelog.d/maintenance/10780-server-init-dead-code.md b/changelog.d/maintenance/10780-server-init-dead-code.md deleted file mode 100644 index ffe204a233..0000000000 --- a/changelog.d/maintenance/10780-server-init-dead-code.md +++ /dev/null @@ -1 +0,0 @@ -- chore(startup): remove `src/server-init.ts` (183 lines, never imported — the boot path is `src/instrumentation-node.ts`) and correct four `"called from server-init.ts"` comments left pointing at the dead entry point (#10780) diff --git a/changelog.d/maintenance/10859-filesize-baseline-fix.md b/changelog.d/maintenance/10859-filesize-baseline-fix.md deleted file mode 100644 index aed0a3fab5..0000000000 --- a/changelog.d/maintenance/10859-filesize-baseline-fix.md +++ /dev/null @@ -1 +0,0 @@ -- fix(quality): rebaseline file-size for #10859's own modelCapabilities.ts/commandCode.ts growth (missed at merge time) diff --git a/changelog.d/maintenance/10875-combos-id-verb-coverage.md b/changelog.d/maintenance/10875-combos-id-verb-coverage.md deleted file mode 100644 index 5610a7ea41..0000000000 --- a/changelog.d/maintenance/10875-combos-id-verb-coverage.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(openapi):** document the `GET` and `PUT` operations on `/api/combos/{id}`, and add an operation-level coverage floor so a missing verb can no longer hide behind a path that already counts as covered ([#10875](https://github.com/diegosouzapw/OmniRoute/pull/10875)) diff --git a/changelog.d/maintenance/10889-feature-flag-count-fix.md b/changelog.d/maintenance/10889-feature-flag-count-fix.md deleted file mode 100644 index fd93221987..0000000000 --- a/changelog.d/maintenance/10889-feature-flag-count-fix.md +++ /dev/null @@ -1 +0,0 @@ -- fix(quality): bump EXPECTED_FEATURE_FLAG_COUNT to 52 for #10889's own new flag (missed at merge time) diff --git a/changelog.d/maintenance/10906-critical-db-state-assertions.md b/changelog.d/maintenance/10906-critical-db-state-assertions.md deleted file mode 100644 index c63f5f0039..0000000000 --- a/changelog.d/maintenance/10906-critical-db-state-assertions.md +++ /dev/null @@ -1 +0,0 @@ -- **test(db):** replace three empty `test.skip` placeholders in the critical DB-state suite with real assertions — `resetDbInstance` must swap the singleton while the on-disk row survives, the on-disk DB must open in WAL journal mode, and `db_meta` must hold the seeded `schema_version` — so a regression in any of those invariants can no longer pass as silently green ([#10906](https://github.com/diegosouzapw/OmniRoute/pull/10906)) diff --git a/changelog.d/maintenance/10982-runtime-ram-coding-agents.md b/changelog.d/maintenance/10982-runtime-ram-coding-agents.md deleted file mode 100644 index 3c0985c68f..0000000000 --- a/changelog.d/maintenance/10982-runtime-ram-coding-agents.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(docker):** document runtime RAM for coding-agent `/v1/responses` (image default 1 GiB heap is dashboard-only; 8–12 GiB heap for agents) ([#10982](https://github.com/diegosouzapw/OmniRoute/issues/10982)) diff --git a/changelog.d/maintenance/11018-database-cache-docs.md b/changelog.d/maintenance/11018-database-cache-docs.md deleted file mode 100644 index a7230d02fd..0000000000 --- a/changelog.d/maintenance/11018-database-cache-docs.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(database):** align the SQLite cache guide with the 65,536 KiB runtime default, supported 1–1,000,000 KiB range, and live Settings application behavior ([#11018](https://github.com/diegosouzapw/OmniRoute/issues/11018)) diff --git a/changelog.d/maintenance/11024-n-instance-scale-out.md b/changelog.d/maintenance/11024-n-instance-scale-out.md deleted file mode 100644 index 82adafe480..0000000000 --- a/changelog.d/maintenance/11024-n-instance-scale-out.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(docker):** document N independent `DATA_DIR`s as the supported large `/v1/responses` scale-out (one V8 heap ≠ host RAM; do not `replicas>1` on one SQLite file) ([#11024](https://github.com/diegosouzapw/OmniRoute/issues/11024)) — thanks @RaviTharuma diff --git a/changelog.d/maintenance/11038-filesize-baseline-fix.md b/changelog.d/maintenance/11038-filesize-baseline-fix.md deleted file mode 100644 index aebc2b9e23..0000000000 --- a/changelog.d/maintenance/11038-filesize-baseline-fix.md +++ /dev/null @@ -1 +0,0 @@ -- fix(quality): rebaseline file-size for modelCapabilities.ts (1016->1072) drift from merged tip fixes (#11034 et al) diff --git a/changelog.d/maintenance/11053-stryker-oauth-autoimport-registration.md b/changelog.d/maintenance/11053-stryker-oauth-autoimport-registration.md deleted file mode 100644 index b2e2141900..0000000000 --- a/changelog.d/maintenance/11053-stryker-oauth-autoimport-registration.md +++ /dev/null @@ -1 +0,0 @@ -- fix(quality): register `tests/unit/authz/oauth-autoimport-local-only.test.ts` in stryker `tap.testFiles` (residual of #11053) diff --git a/changelog.d/maintenance/11160-drain-v3850-basereds-docs-counts-orphan-test.md b/changelog.d/maintenance/11160-drain-v3850-basereds-docs-counts-orphan-test.md deleted file mode 100644 index e695a2b8fc..0000000000 --- a/changelog.d/maintenance/11160-drain-v3850-basereds-docs-counts-orphan-test.md +++ /dev/null @@ -1 +0,0 @@ -- chore(quality): drain two `release/v3.8.50` base-reds — refresh the drifted doc counts (159 migrations, 56 free-forever providers, 40 free-tier pools, incl. the 42 `llm.txt` locale mirrors) and move `uncloseai-noauth.test.ts` to a collected path so the UncloseAI no-auth regression guard actually runs (#11160) diff --git a/changelog.d/maintenance/11247-ratchet-no-unused-vars.md b/changelog.d/maintenance/11247-ratchet-no-unused-vars.md deleted file mode 100644 index f86559b7b6..0000000000 --- a/changelog.d/maintenance/11247-ratchet-no-unused-vars.md +++ /dev/null @@ -1 +0,0 @@ -- **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)) diff --git a/changelog.d/maintenance/11342-pnpm-optional-peers-license-policy.md b/changelog.d/maintenance/11342-pnpm-optional-peers-license-policy.md deleted file mode 100644 index 55df9af673..0000000000 --- a/changelog.d/maintenance/11342-pnpm-optional-peers-license-policy.md +++ /dev/null @@ -1,3 +0,0 @@ -- **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)). diff --git a/changelog.d/maintenance/11345-changelog-reconciliation-ledger.md b/changelog.d/maintenance/11345-changelog-reconciliation-ledger.md deleted file mode 100644 index e9cb8e877c..0000000000 --- a/changelog.d/maintenance/11345-changelog-reconciliation-ledger.md +++ /dev/null @@ -1 +0,0 @@ -- **ci(changelog):** replace the broad removal bypass with an exact, hash-bound reconciliation ledger and bind merge-train checks to their requested release base ([#11345](https://github.com/diegosouzapw/OmniRoute/pull/11345)). diff --git a/changelog.d/maintenance/11356-readme-live-metrics.md b/changelog.d/maintenance/11356-readme-live-metrics.md deleted file mode 100644 index 3d06965062..0000000000 --- a/changelog.d/maintenance/11356-readme-live-metrics.md +++ /dev/null @@ -1,5 +0,0 @@ -- **docs(readme):** reconcile live v3.8.50 provider, free-tier, CLI, routing, test, - community, sponsor, acknowledgment, and SVG metrics with their audited source - denominators, including a deduplicated OmniRoute-in-Action snapshot and distinct - contributor rankings for merged pull requests, GitHub-attributed commits, and Git history - ([#11356](https://github.com/diegosouzapw/OmniRoute/pull/11356)). diff --git a/changelog.d/maintenance/11363-openapi-try-operation-coverage.md b/changelog.d/maintenance/11363-openapi-try-operation-coverage.md deleted file mode 100644 index f666967041..0000000000 --- a/changelog.d/maintenance/11363-openapi-try-operation-coverage.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(openapi):** document the conditionally management-authenticated, same-origin `POST /api/openapi/try` proxy contract and restore the release branch's operation-coverage ratchet ([#11363](https://github.com/diegosouzapw/OmniRoute/pull/11363)) diff --git a/changelog.d/maintenance/11381-video-bridge-fu07-structural-sampling.md b/changelog.d/maintenance/11381-video-bridge-fu07-structural-sampling.md deleted file mode 100644 index 17a48aa416..0000000000 --- a/changelog.d/maintenance/11381-video-bridge-fu07-structural-sampling.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(video-bridge):** make opt-in segment-aware sampling use one bounded structural FFmpeg pass (scene, freeze, blur, exposure, and SI/TI), preserve long trailing segments, fail open to uniform sampling, and add real-media structural-oracle, overhead, post-dedup caption-call, and false-positive evidence while holding unconfigured model quality and gain-versus-cost claims ([#11381](https://github.com/diegosouzapw/OmniRoute/pull/11381)). diff --git a/changelog.d/maintenance/7786-management-auth-guide.md b/changelog.d/maintenance/7786-management-auth-guide.md deleted file mode 100644 index 54f84a79b9..0000000000 --- a/changelog.d/maintenance/7786-management-auth-guide.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(auth):** distinguish dashboard sessions, `oma_live_…` Access Tokens, manage-scoped API keys, and inference keys ([#7786](https://github.com/diegosouzapw/OmniRoute/issues/7786)) diff --git a/changelog.d/maintenance/embeddings-client-runbook.md b/changelog.d/maintenance/embeddings-client-runbook.md deleted file mode 100644 index da47b8d261..0000000000 --- a/changelog.d/maintenance/embeddings-client-runbook.md +++ /dev/null @@ -1 +0,0 @@ -- **docs:** add an embeddings client runbook with live-verified working/broken model ids and Hindsight 0.9.1 / Memorix 1.6.0 notes — thanks @RaviTharuma diff --git a/changelog.d/maintenance/env-doc-sync-adhoc-bot.md b/changelog.d/maintenance/env-doc-sync-adhoc-bot.md deleted file mode 100644 index dbd759be29..0000000000 --- a/changelog.d/maintenance/env-doc-sync-adhoc-bot.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(ci):** ignore ad-hoc `BOT_TOKEN`/`BOT_URL` in env-doc-sync (scripts/ad-hoc mesh helpers, not runtime config) diff --git a/changelog.d/maintenance/kimi-health-check-jitter-determinism.md b/changelog.d/maintenance/kimi-health-check-jitter-determinism.md deleted file mode 100644 index 5b57eaa422..0000000000 --- a/changelog.d/maintenance/kimi-health-check-jitter-determinism.md +++ /dev/null @@ -1 +0,0 @@ -- **test(kimi):** the Kimi background health sweep no longer draws its refresh window inside the assertion. `checkKimiWebConnectionIfNeeded` spreads the refresh over `[60, 240)` seconds before expiry so a fleet of connections does not stampede the token endpoint, and the test used a token expiring in 90 seconds and asserted that a refresh happened — which is true only when the draw lands at 90 or above, i.e. 150 of the 180 possible values. Measured: the test fails 1 run in 6 (16.7% by construction; 4 of 20 local runs), and it is what the Node 26 nightly hit and reported as a Node-compat break (#11361). The spread is now `defaultKimiRefreshJitterSec()` and the window is injectable as `jitterSecFn`, so the test decides it instead of rolling for it; production behaviour is unchanged. Cases were added for a token outside the window and for the default spread's range. diff --git a/changelog.d/maintenance/regen-translate-path-golden-freebuff.md b/changelog.d/maintenance/regen-translate-path-golden-freebuff.md deleted file mode 100644 index 7822df2283..0000000000 --- a/changelog.d/maintenance/regen-translate-path-golden-freebuff.md +++ /dev/null @@ -1 +0,0 @@ -- chore(test): regenerate the provider/translate-path golden snapshot to reflect freebuff (#10531), fixing a base-red left by that merge (freebuff/freeinference key ordering only, no value changes). diff --git a/changelog.d/maintenance/release-v3850-base-reds-20260817.md b/changelog.d/maintenance/release-v3850-base-reds-20260817.md deleted file mode 100644 index d435b50096..0000000000 --- a/changelog.d/maintenance/release-v3850-base-reds-20260817.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(release):** resync the v3.8.50 provider and CLI catalogs, register the existing ChatCore mutation-coverage test, and document the local ZCode handshake identifier so the release quality gates reflect the current tree without changing ratchet baselines. diff --git a/changelog.d/maintenance/release-v3850-basereds-error-helper-20260819.md b/changelog.d/maintenance/release-v3850-basereds-error-helper-20260819.md deleted file mode 100644 index e89d53ab49..0000000000 --- a/changelog.d/maintenance/release-v3850-basereds-error-helper-20260819.md +++ /dev/null @@ -1,3 +0,0 @@ -- **fix(ci):** route `open-sse/handlers/imageGeneration/providers/geminiWeb.ts`'s b64_json - download-failure message through `sanitizeErrorMessage()` instead of embedding a raw - `err.message`, clearing the `check:error-helper` base-red on `release/v3.8.50` (#9985). diff --git a/changelog.d/maintenance/release-v3850-basereds-eslint-deadcode-vitest-20260819.md b/changelog.d/maintenance/release-v3850-basereds-eslint-deadcode-vitest-20260819.md deleted file mode 100644 index 905d338575..0000000000 --- a/changelog.d/maintenance/release-v3850-basereds-eslint-deadcode-vitest-20260819.md +++ /dev/null @@ -1,20 +0,0 @@ -- **fix(ci):** drain three more base-reds on `release/v3.8.50` (#9985). ESLint was reporting - 219 errors locally (vs. 25 in the last CI run) — all from `react-hooks/set-state-in-effect`, - `react-hooks/preserve-manual-memoization`, `react-hooks/immutability`, - `react-hooks/static-components`, `react-hooks/refs` and `react-hooks/purity`, six React - Compiler lint rules that `eslint-plugin-react-hooks` v7 turns on by default and that were - never frozen in `config/quality/eslint-suppressions.json` after the dependency bump. Froze - the pre-existing violations for those six rules via ESLint's native - `--suppress-rule`/`--suppressions-location` mechanism (the same pattern already used for - `@next/next/no-location-assign-relative-destination`) — no application code changed, no rule - disabled, only genuinely-new violations stay blocking. `check:dead-code` was at 418 against a - 415 baseline: removed the unused `src/lib/quota/providerCapabilities.ts` file and the unused - `ProviderQuotaMonitor` interface in `providerQuotaTelemetry.ts` (both dead since PR #10148, - 2026-08-18, confirmed via `grep`/knip cross-reference), landing at 416; the residual +1 could - not be attributed to a single recent commit after checking every dead-list entry touched - since the 2026-08-14 baseline measurement, so it is rebaselined with the investigation - recorded in `quality-baseline.json`. `tests/unit/autoCombo/tieredRotation.test.ts`'s - "rotates across all 43 Cerebras connection IDs" case was hitting vitest's 5000ms default - timeout on a 200-iteration synchronous `selectProvider()` loop under shared-devbox - contention (load average 40-60+ observed) — widened its explicit timeout to 20000ms; the - assertion itself is unchanged. diff --git a/changelog.d/maintenance/release-v3850-basereds-glm-family-20260819.md b/changelog.d/maintenance/release-v3850-basereds-glm-family-20260819.md deleted file mode 100644 index 04985623c0..0000000000 --- a/changelog.d/maintenance/release-v3850-basereds-glm-family-20260819.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(tests):** drain two base-reds on the release branch — `auto/glm` now expects the Cloudflare AI Playground backend (its registry advertises `zai-org/glm-5.2` and `zai-org/glm-4.7-flash`, so it belongs in the family pool by the same rule already documented for `auggie`, `devin-cli-agentic` and `zcode`), and the ESLint gate is green again after the GitLab executor test dropped its five `as any` casts for a declared response shape and the CLI OAuth suppression count caught up with the two casts #10491 added. diff --git a/changelog.d/maintenance/release-v3850-basereds-stream-utils-20260820.md b/changelog.d/maintenance/release-v3850-basereds-stream-utils-20260820.md deleted file mode 100644 index 98b62cd448..0000000000 --- a/changelog.d/maintenance/release-v3850-basereds-stream-utils-20260820.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(tests):** realign the two `stream-utils` passthrough cases that still asserted the pre-#10017 SSE framing — the event-boundary case declares the OpenAI Responses client format it actually exercises, and the metadata case now pins that surviving lines stay inside one event instead of expecting the `:`/`id:` control lines that #10473 stopped forwarding to every client format. diff --git a/changelog.d/maintenance/release-v3850-basereds-testdrift-20260819.md b/changelog.d/maintenance/release-v3850-basereds-testdrift-20260819.md deleted file mode 100644 index f4deae6aae..0000000000 --- a/changelog.d/maintenance/release-v3850-basereds-testdrift-20260819.md +++ /dev/null @@ -1,12 +0,0 @@ -- **fix(tests):** drain several base-reds on `release/v3.8.50` (#9985) that were all instances - of the same pattern — a legitimate product change landed without updating the test that - asserted the old behavior: `tests/unit/glm-provider-model-import-route.test.ts` (12 tests) - and `tests/unit/model-sync-route.test.ts` (2 tests) predate #10603's "upstream model sync is - opt-in and manual overrides are preserved" change; `tests/unit/antigravity-model-aliases.test.ts` - predated #10537 retiring the collapsed `gemini-3.7-flash` alias in favor of its three tiered - ids. Also fixes a real data drift in `open-sse/config/freeModelCatalog.data.ts` (the `qwen-web` - free-catalog entry still pointed at the retired `qwen3.8-max-preview` id instead of the - current `qwen3.8-max`), corrects the zh-TW `providers.autoFetchModelsTooltip` string to the - glossary-canonical 快取 instead of 緩存, and removes an unused default export from - `src/lib/oauth/providers/zed-hosted.ts` (the named export already covers every consumer) to - shave one symbol off the `check:dead-code` ratchet regression. diff --git a/changelog.d/maintenance/release-v3850-docs-env-basereds-20260817.md b/changelog.d/maintenance/release-v3850-docs-env-basereds-20260817.md deleted file mode 100644 index d2ec7afbd4..0000000000 --- a/changelog.d/maintenance/release-v3850-docs-env-basereds-20260817.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(release):** synchronize migration-count documentation and document the opt-in `PROXY_LOG_INCLUDE_IPS` logging flag so the v3.8.50 quality gates match the release tree. diff --git a/changelog.d/maintenance/vi-harimport-parity.md b/changelog.d/maintenance/vi-harimport-parity.md deleted file mode 100644 index b08b8dc92f..0000000000 --- a/changelog.d/maintenance/vi-harimport-parity.md +++ /dev/null @@ -1 +0,0 @@ -- fix(i18n): translate the 14 `providers.harImport*` keys into Vietnamese (parity gap left by #11069)