diff --git a/.agents/workflows/fix-ci.md b/.agents/workflows/fix-ci.md deleted file mode 100644 index dd299c50c5..0000000000 --- a/.agents/workflows/fix-ci.md +++ /dev/null @@ -1,182 +0,0 @@ -# Fix CI Workflow - -Look up the latest GitHub Actions CI run for the current release branch, diagnose all failures, fix them locally, push, and wait for the new CI run to go green before notifying the user. - ---- - -## Phase 1: Identify the Failing CI Run - -### 1. Determine the current release version and branch - -// turbo - -```bash -cd /home/diegosouzapw/dev/proxys/9router -VERSION=$(node -p "require('./package.json').version") -BRANCH=$(git branch --show-current) -echo "Version: $VERSION" -echo "Branch: $BRANCH" -``` - -### 2. Find the latest CI run for the release PR - -// turbo - -```bash -cd /home/diegosouzapw/dev/proxys/9router -# Find the PR number for the release branch -PR_NUMBER=$(gh pr list --repo diegosouzapw/OmniRoute --head "$BRANCH" --json number --jq '.[0].number') -echo "PR: #$PR_NUMBER" - -# Get the latest CI run -RUN_ID=$(gh run list --repo diegosouzapw/OmniRoute --branch "$BRANCH" --workflow ci.yml --limit 1 --json databaseId --jq '.[0].databaseId') -echo "Latest CI Run: $RUN_ID" -echo "URL: https://github.com/diegosouzapw/OmniRoute/actions/runs/$RUN_ID" -``` - ---- - -## Phase 2: Diagnose Failures - -### 3. List all failing jobs - -// turbo - -```bash -cd /home/diegosouzapw/dev/proxys/9router -RUN_ID=$(gh run list --repo diegosouzapw/OmniRoute --branch "$(git branch --show-current)" --workflow ci.yml --limit 1 --json databaseId --jq '.[0].databaseId') -gh run view "$RUN_ID" --repo diegosouzapw/OmniRoute --json jobs --jq '.jobs[] | select(.conclusion == "failure") | {name: .name, conclusion: .conclusion, steps: [.steps[] | select(.conclusion == "failure") | .name]}' -``` - -### 4. Download and analyze failure logs - -// turbo - -```bash -cd /home/diegosouzapw/dev/proxys/9router -RUN_ID=$(gh run list --repo diegosouzapw/OmniRoute --branch "$(git branch --show-current)" --workflow ci.yml --limit 1 --json databaseId --jq '.[0].databaseId') -gh run view "$RUN_ID" --repo diegosouzapw/OmniRoute --log-failed 2>&1 | grep -aE "not ok|FAIL|Error:|error:|AssertionError|expected|actual" | grep -v "node_modules\|runner\|git version" | head -50 -``` - -### 5. Classify each failure - -For each failing job, determine the root cause category: - -| Category | Pattern | Fix Strategy | -| ------------------ | ---------------------------------- | ------------------------------------------ | -| **docs-sync** | OpenAPI/CHANGELOG version mismatch | Run `/version-bump` step 7-8 | -| **Test assertion** | `not ok` + `AssertionError` | Update test expectations to match new code | -| **E2E flaky** | Auth-related 401/403/307 | Make tests tolerate auth states | -| **Coverage gate** | `below threshold` | Add more tests or adjust threshold | -| **Lint** | ESLint errors | Fix code or update rules | -| **Build** | Compilation errors | Fix TypeScript issues | - ---- - -## Phase 3: Apply Fixes - -### 6. Fix each failure - -For each classified failure: - -1. **Read the failing test file** to understand the assertion -2. **Read the production source** to understand the new behavior -3. **Update the test** to match the current behavior -4. **Run the test locally** to verify the fix - -// turbo - -```bash -cd /home/diegosouzapw/dev/proxys/9router -# Run the specific failing test file(s) to confirm fixes -# Example: node --import tsx/esm --test tests/unit/FAILING_FILE.test.mjs -``` - -### 7. Run the full local test suite - -// turbo - -```bash -cd /home/diegosouzapw/dev/proxys/9router -npm test -``` - -### 8. Run docs-sync check - -// turbo - -```bash -cd /home/diegosouzapw/dev/proxys/9router -npm run check:docs-sync -``` - ---- - -## Phase 4: Push and Monitor - -### 9. Commit and push fixes - -// turbo-all - -```bash -cd /home/diegosouzapw/dev/proxys/9router -git add -A -git commit -m "fix(tests): align CI tests with release changes" -git push origin "$(git branch --show-current)" -``` - -### 10. Wait for CI to trigger and find the new run - -// turbo - -```bash -cd /home/diegosouzapw/dev/proxys/9router -sleep 15 -BRANCH=$(git branch --show-current) -NEW_RUN_ID=$(gh run list --repo diegosouzapw/OmniRoute --branch "$BRANCH" --workflow ci.yml --limit 1 --json databaseId --jq '.[0].databaseId') -echo "New CI Run: $NEW_RUN_ID" -echo "URL: https://github.com/diegosouzapw/OmniRoute/actions/runs/$NEW_RUN_ID" -``` - -### 11. Monitor the CI run - -// turbo - -```bash -cd /home/diegosouzapw/dev/proxys/9router -BRANCH=$(git branch --show-current) -NEW_RUN_ID=$(gh run list --repo diegosouzapw/OmniRoute --branch "$BRANCH" --workflow ci.yml --limit 1 --json databaseId --jq '.[0].databaseId') -gh run watch "$NEW_RUN_ID" --repo diegosouzapw/OmniRoute --exit-status -``` - -If `gh run watch` exits with 0, the CI is green. If it exits with non-zero, go back to Phase 2 and repeat. - -### 12. 🛑 STOP — Notify User - -Present a summary to the user: - -- **Previous CI run**: URL, list of failures -- **Root causes**: What broke and why -- **Fixes applied**: What tests were changed -- **New CI run**: URL, all-green status -- **PR status**: Ready for review/merge - ---- - -## Common CI Failure Patterns - -| Failure | Root Cause | Fix | -| ------------------------------------------ | -------------------------------------- | ----------------------------- | -| `docs-sync FAIL - OpenAPI version differs` | Version not synced after bump | `sed -i` openapi.yaml | -| `docs-sync FAIL - CHANGELOG first section` | Missing `## [Unreleased]` header | Add unreleased section | -| `not ok - cleanupExpiredLogs` | Return shape changed (new fields) | Update `assert.deepEqual` | -| `not ok - email masking` | Email now masked in call logs | Assert masked pattern instead | -| `E2E /api/providers` returns non-200 | Auth enabled in CI, endpoint protected | Accept 401/403 as valid | -| `coverage below 60%` | New untested code | Add unit tests | - -## Notes - -- This workflow is **iterative**: if the first fix attempt doesn't clear all failures, repeat Phases 2-4. -- Always run tests **locally** before pushing to avoid wasting CI minutes. -- The CI is triggered automatically on push to branches with open PRs to `main`. -- Use `gh run watch` to monitor in real-time instead of polling. diff --git a/.agents/workflows/fix-cli-node22-ts-entrypoint.md b/.agents/workflows/fix-cli-node22-ts-entrypoint.md deleted file mode 100644 index a527592a14..0000000000 --- a/.agents/workflows/fix-cli-node22-ts-entrypoint.md +++ /dev/null @@ -1,27 +0,0 @@ -# Workflow: Fix CLI Node 22 TS Entrypoint Issue - -## Issue Description - -In OmniRoute >= 3.6.6, the `package.json` declares the main CLI binary as `bin/omniroute.ts`. While Node 22 introduced experimental support for executing TypeScript files natively via the `--experimental-strip-types` flag (and `--experimental-transform-types`), Node.js explicitly disables this feature for any files loaded from inside a `node_modules` directory. - -When users install `omniroute` globally (or locally) via npm, the CLI shim points to `bin/omniroute.ts` inside `node_modules`. Running `omniroute` on Node 22 results in: -`Error [ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING]: Stripping types is currently unsupported for files under node_modules` - -This makes the CLI completely unusable out-of-the-box on Node 22, despite the `engines` field claiming support for `>=22.22.2`. - -## Proposed Solution - -The CLI entrypoint distributed in the NPM package must be a JavaScript file, not a TypeScript file. - -1. Restore `bin/omniroute.mjs` as the actual CLI entrypoint, or implement a build step during `npm run build:cli` that compiles `bin/omniroute.ts` to `bin/omniroute.mjs` before publishing. -2. Update `package.json` to point the `bin` field back to the compiled `.js`/`.mjs` file: - ```json - "bin": { - "omniroute": "bin/omniroute.mjs" - } - ``` -3. Ensure `scripts/prepublish.ts` handles the compilation or validation of the binary entrypoint correctly so this regression doesn't happen again. - -## Task - -Please implement this fix, ensure the tests pass, and create a Pull Request against the main branch. diff --git a/.agents/workflows/generate-release.md b/.agents/workflows/generate-release.md index 3a1c6c3c9c..8d0ac8ca17 100644 --- a/.agents/workflows/generate-release.md +++ b/.agents/workflows/generate-release.md @@ -52,19 +52,19 @@ Before creating the release, you must ensure the codebase and supply chain are s git checkout -b release/v2.x.y ``` -### 2. Determine new version +### 2. Determine and sync version -Check current version in `package.json` and increment the **patch** number only: +Check current version in `package.json`: ```bash grep '"version"' package.json ``` -Version format: `2.x.y` — examples: - -- `2.1.2` → `2.1.3` (patch) -- `2.1.9` → `2.1.10` (patch) -- `2.1.10` → `2.2.0` (minor threshold — do manually with `sed`) +> **🔴 BRANCH-VERSION PARITY RULE**: The logical version in `package.json` MUST exactly match the release branch name. For example, if you are on `release/v3.7.0`, the version in `package.json` MUST be `3.7.0`. +> +> - If this is the FIRST time generating a release for a new minor/major branch (e.g., bumping from 3.6.9 to 3.7.0), you MUST ensure the version is bumped to match the new branch logic. +> - If you are just bumping a patch on the current branch (e.g., 3.6.9 to 3.6.10), use: +> `npm version patch --no-git-tag-version` > **⚠️ ATOMIC COMMIT RULE — Version bump MUST happen before committing feature files.** > @@ -97,15 +97,29 @@ npm install ### 4. Finalize CHANGELOG.md -Replace `[Unreleased]` header with the new version and date. -Keep an empty `## [Unreleased]` section above it. +> **🔴 NO MIXUPS RULE**: Ensure you do NOT mix the backlog of the previous version with the new one. The new version section must ONLY contain the features and fixes for the current release. + +Replace the `[Unreleased]` header with the new version and date. +Keep an empty `## [Unreleased]` section above it, separated by a horizontal rule (`---`). ```markdown ## [Unreleased] --- -## [2.x.y] — YYYY-MM-DD +## [3.7.0] — 2026-04-19 + +### ✨ New Features + +- ... + +### 🐛 Bug Fixes + +- ... + +--- + +## [3.6.9] — 2026-04-19 ``` ### 5. Update openapi.yaml version ⚠️ MANDATORY diff --git a/.env.example b/.env.example index 9aa731e283..9979052ab9 100644 --- a/.env.example +++ b/.env.example @@ -404,7 +404,7 @@ QODER_OAUTH_CLIENT_SECRET=4Z3YjXycVsQvyGF1etiNlIBB4RsqSDtW # Update these when providers release new CLI versions to avoid blocks. CLAUDE_USER_AGENT=claude-cli/1.0.83 (external, cli) -CODEX_USER_AGENT=codex-cli/0.92.0 (Windows 10.0.26100; x64) +CODEX_USER_AGENT=codex-cli/0.125.0 (Windows 10.0.26100; x64) GITHUB_USER_AGENT=GitHubCopilotChat/0.26.7 ANTIGRAVITY_USER_AGENT=antigravity/1.104.0 darwin/arm64 KIRO_USER_AGENT=AWS-SDK-JS/3.0.0 kiro-ide/1.0.0 @@ -536,6 +536,12 @@ APP_LOG_TO_FILE=true # Default: 20 # APP_LOG_MAX_FILES=20 +# How often OmniRoute checks whether the active log file has exceeded +# APP_LOG_MAX_FILE_SIZE and triggers a rotation. Set lower for very verbose +# services to prevent log files from growing large between checks. +# Accepts milliseconds. Default: 60000 (1 minute) +# APP_LOG_ROTATION_CHECK_INTERVAL_MS=60000 + # Days to keep request/call log entries in the database before auto-cleanup. # Default: 7 # CALL_LOG_RETENTION_DAYS=7 diff --git a/.github/workflows/build-fork.yml b/.github/workflows/build-fork.yml new file mode 100644 index 0000000000..89595de66b --- /dev/null +++ b/.github/workflows/build-fork.yml @@ -0,0 +1,41 @@ +name: Build Fork Image (ghcr.io) + +on: + workflow_dispatch: + +permissions: + contents: read + packages: write + +jobs: + build: + name: Build and Push to ghcr.io + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: fix/claude-thinking-mapping + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + target: runner-base + platforms: linux/amd64 + push: true + tags: | + ghcr.io/inkorcloud/omniroute:fix-claude-thinking-mapping + ghcr.io/inkorcloud/omniroute:latest + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.gitignore b/.gitignore index 783740a7d7..3ec3d24321 100644 --- a/.gitignore +++ b/.gitignore @@ -94,6 +94,8 @@ docs/* !docs/screenshots/ !docs/i18n/ !docs/i18n/** +!docs/features/ +!docs/features/** !docs/A2A-SERVER.md !docs/AUTO-COMBO.md !docs/MCP-SERVER.md @@ -116,6 +118,7 @@ test-results/ playwright-report/ blob-report/ cloud/ +.tmp/ # Security Analysis (standalone project with own git) security-analysis/ @@ -176,3 +179,6 @@ bin/omniroute.mjs .omc/ audit-report.json bun.lock + +# Private environment variables for .http-client +http-client.private.env.json diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000000..e746658575 --- /dev/null +++ b/.npmrc @@ -0,0 +1,4 @@ +# @lobehub/icons declares UI peers that are not needed by our deep icon imports. +# Keeping peer auto-install disabled prevents npm from pulling @lobehub/ui/mermaid +# back into the tree and reopening npm audit findings for unused packages. +legacy-peer-deps=true diff --git a/AGENTS.md b/AGENTS.md index f80682d4f0..39b6ae3687 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,7 @@ Unified AI proxy/router — route any LLM through one endpoint. Multi-provider s with **100+ providers** (OpenAI, Anthropic, Gemini, DeepSeek, Groq, xAI, Mistral, Fireworks, Cohere, NVIDIA, Cerebras, Pollinations, Puter, Cloudflare AI, HuggingFace, DeepInfra, SambaNova, Meta Llama API, Moonshot AI, AI21 Labs, Databricks, Snowflake, and many more) -with **MCP Server** (25 tools), **A2A v0.3 Protocol**, and **Electron desktop app**. +with **MCP Server** (29 tools), **A2A v0.3 Protocol**, and **Electron desktop app**. ## Stack @@ -303,12 +303,14 @@ Policy engine modules: `policyEngine.ts`, `comboResolver.ts`, `costRules.ts`, ### MCP Server (`open-sse/mcp-server/`) -25 tools, 3 transports (stdio / SSE / Streamable HTTP). Scoped auth (10 scopes), Zod schemas. +29 tools, 3 transports (stdio / SSE / Streamable HTTP). Scoped auth (10 scopes), Zod schemas. -**Core tools** (18): get_health, list_combos, get_combo_metrics, switch_combo, check_quota, -route_request, cost_report, list_models_catalog, simulate_route, set_budget_guard, +**Core tools** (20): get_health, list_combos, get_combo_metrics, switch_combo, check_quota, +route_request, cost_report, list_models_catalog, web_search, simulate_route, set_budget_guard, set_routing_strategy, set_resilience_profile, test_combo, get_provider_metrics, -best_combo_for_task, explain_route, get_session_snapshot, sync_pricing. +best_combo_for_task, explain_route, get_session_snapshot, db_health_check, sync_pricing. + +**Cache tools** (2): cache_stats, cache_flush. **Memory tools** (3): memory_search, memory_add, memory_clear. diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e7189ab30..f743900cf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,148 @@ ## [Unreleased] +### 🐛 Bug Fixes + +- **fix(mitm):** Compile MITM utilities as NodeNext ESM during prepublish, copy the CommonJS MITM server into the standalone artifact, and resolve MITM data paths without relying on Next.js aliases in packaged runtime. +- **fix(build):** Move the local `.tmp/wine32` Wine prefix out of the isolated Next.js build path so Windows Electron packaging artifacts cannot trigger `EACCES` scans during Node 24 builds. +- **fix(build):** Copy the `wreq-js` native runtime directory into the isolated Next.js standalone output so packaged Playwright/E2E starts can load the instrumentation hook on Linux. +- **feat(providers):** Integrate AgentRouter as a new OpenAI-compatible passthrough provider with $200 free credits via sign-up (Issue #1572). +- **feat(ui):** Implement on-demand per-model testing in the provider dashboard, allowing single-token diagnostic checks without triggering rate-limits (Issue #1532). +- **fix(api):** Validate the Codex Responses websocket bridge and `/v1/batches` JSON payloads with Zod before use, keeping `request.json()` route validation green and returning explicit 400 responses for invalid bodies. +- **fix(providers):** Add explicit typing to provider alias and category helpers so the strict `typecheck:noimplicit:core` CI gate passes. +- **fix(ui):** Keep the upstream proxy provider detail page labeled with a fallback "Managed via Upstream Proxy Settings" management surface when translations are unavailable. +- **fix(electron):** Harden the production desktop CSP by removing `unsafe-eval` outside development and adding object, base URI, form action, frame ancestor, and worker restrictions. +- **fix(cli):** Replace shell-interpolated setup and privileged command execution paths with argument-based `spawn`/`execFile` helpers for database setup, Tailscale sudo commands, MITM DNS edits, and certificate install/uninstall flows. +- **fix(ui):** Keep provider icons resilient by using direct `@lobehub/icons` components first, then local PNG/SVG fallbacks, avoiding the `@lobehub/ui` peer runtime in the dashboard. + +### 📦 Dependencies + +- **deps:** Update `@lobehub/icons` to `5.5.4`, add explicit `react-is@19.2.5` for Recharts, pin npm installs to skip unused peer auto-installs, and override Electron's transitive `@xmldom/xmldom` to `0.9.10` so audit findings stay closed. + +--- + +## [3.7.0] — 2026-04-24 + +### ✨ New Features + +- **feat(provider):** add ChatGPT Web (Plus/Pro) session provider (#1593) +- **feat(provider):** add Baidu Qianfan chat provider (#1582) +- **feat(codex):** support GPT-5.5 responses websocket (#1573) +- **feat(sse):** Codex CLI image_generation + DALL-E-style image route (#1544) +- **feat(dashboard):** Complete the reconciled v3.7.0 dashboard task set: MCP cache tools and count, video endpoint visibility, provider taxonomy, upstream proxy visibility, provider count badges, costs overview, eval suite management, Custom CLI builder, ACP-focused Agents copy, Translator stream transformer, logs convergence, learned rate-limit health cards, docs expansion, and active request payload inspection. +- **feat(mcp):** Register `omniroute_cache_stats` and `omniroute_cache_flush` across MCP schemas, server registration, handlers, docs, and tests. +- **feat(providers):** Complete the v3.7.0 provider onboarding wave with self-hosted/local providers (`lm-studio`, `vllm`, `lemonade`, `llamafile`, `triton`, `docker-model-runner`, `xinference`, `oobabooga`), OpenAI-compatible gateways (`glhf`, `cablyai`, `thebai`, `fenayai`, `empower`, `poe`), enterprise providers (`datarobot`, `azure-openai`, `azure-ai`, `bedrock`, `watsonx`, `oci`, `sap`), specialty providers (`clarifai`, `modal`, `reka`, `nous-research`, `nlpcloud`, `petals`, `vertex-partner`), `amazon-q`, GitLab/GitLab Duo, and Chutes.ai. +- **feat(providers):** Add Cloudflare Workers AI integration and UI support for robust backend execution. +- **feat(telemetry):** Implement proactive public IP capture from client headers (`x-forwarded-for`, `x-real-ip`, etc.) within `safeLogEvents` for accurate database observability. +- **feat(audio):** Add AWS Polly as an audio speech provider with SigV4 request signing, static engine catalog, provider validation, managed-provider UI coverage, and sanitization for AWS secret/session fields. +- **feat(search):** Add You.com search provider support with dashboard discovery, validation, livecrawl option handling, and search handler normalization. +- **feat(video):** Add RunwayML task-based video generation support, task polling, provider catalog metadata, validation, and dashboard/model-list coverage. +- **feat(providers):** Add search functionality to the providers dashboard with i18n support. (#1511 — thanks @th-ch) +- **feat(providers):** Register 6 new models in the opencode-go provider catalog. (#1510 — thanks @kang-heewon) +- **feat(providers):** Add ModelScope provider (Chinese AI marketplace) with Kimi K2.5, GLM-5, and Step-3.5-Flash integration. (#1430 — thanks @clousky2020) +- **feat(providers):** Add LM Studio as an OpenAI-compatible local provider for self-hosted model inference. +- **feat(providers):** Add Grok 4.3 thinking model support for xAI web executor requests. +- **feat(core):** Implement provider-level Circuit Breaker to prevent cascading failures across connections, enforcing a 10-minute cooldown after 5 consecutive transient failures. (#1430) +- **feat(core):** Add daily quota exhaustion lock to detect "quota exceeded" signals and lock the specific model until midnight. (#1430) +- **feat(core):** Auto-inject `stream_options.include_usage = true` for OpenAI format streams to guarantee token usage is reported correctly during streaming. (#1423) +- **feat(core):** Add OpenAI Batch Processing API support — submit, monitor, and manage batch jobs through the proxy with full lifecycle tracking. +- **feat(vision-bridge):** Add automatic image description fallback for non-vision models via `VisionBridgeGuardrail` (priority 5). Intercepts image-bearing requests to non-vision models, extracts descriptions via a configurable vision model (default: gpt-4o-mini), and replaces images with text before forwarding. Fails open on any error. (#1476) +- **feat(dashboard):** Introduce real-time model status badges with countdown timers in the provider detail and combo panel interfaces. (#1430) +- **feat(dashboard):** Add Batch/File management data grid with full i18n translations for batch processing workflows. (#1479) +- **feat(usage):** MiniMax + MiniMax-CN quota tracking in provider limits dashboard. (#1516) +- **feat(providers):** Fix OpenRouter remote discovery and unify managed model sync. (#1521) +- **feat(providers):** Implement provider and account-level concurrency cap enforcement (`maxConcurrent`) using robust semaphore mechanisms. (#1524) +- **feat(core):** Implement Hermes CLI config generation and message content stripping. (#1475) +- **feat(combos):** Add expert combo configuration mode for advanced routing controls. (#1547) +- **feat(tunnels):** Add Tailscale tunnel management routes and runtime helpers for install, login, daemon start, enable/disable, and health checks. + +### 🐛 Bug Fixes + +- **fix(codex):** WebSocket memory retention and weekly limit handling (#1581) +- **fix(providers):** Default models list logic (#1577) +- **fix(ui):** Dashboard endpoint URL hydration respects `NEXT_PUBLIC_BASE_URL` when behind a reverse proxy (#1579) +- **fix(providers):** Restore strict PascalCase header masquerading for Claude Code to resolve HTTP 429 upstream errors (#1556) +- **fix(sse):** make Responses passthrough robust for size-sensitive clients (#1580) +- **fix(codex):** update client version for gpt-5.5 (#1578) +- **fix(vision-bridge):** force GPT-family image fallback (#1571) +- **fix(claude):** skip adaptive thinking defaults for unsupported models (#1563) +- **fix(claude):** preserve tool_result adjacency in native and CC-compatible paths (#1555) +- **fix(reasoning):** Preserve OpenAI Chat Completions `reasoning_effort` through assistant-prefill requests and label OpenAI request protocols explicitly as `OpenAI-Chat` or `OpenAI-Responses`. (#1550) +- **fix(codex):** Fix Codex auto-review model routing so review traffic resolves to the intended configured model. (#1551) +- **fix(resilience):** Route HTTP 429 cooldowns through runtime settings so cooldown behavior follows the configured resilience profile. (#1548) +- **fix(providers):** Normalize Anthropic header keys to lowercase in the provider registry to avoid duplicate or case-variant upstream headers. (#1527) +- **fix(providers):** Preserve audio, embedding, rerank, image, video, and OpenAI-compatible alias metadata when `/v1/models` merges static and discovered catalogs. +- **fix(providers):** Discover Azure OpenAI deployments from resource endpoints using `api-key` auth and configurable API versions. +- **fix(providers):** Keep local OpenAI-style providers authless when no API key is configured, including the Lemonade Server default endpoint. +- **fix(translator):** Preserve Antigravity default system instructions and caller-provided system prompts as separate Gemini `systemInstruction` parts instead of concatenating them. +- **fix(security):** Sanitize provider-specific AWS secrets and session tokens from provider management API responses. +- **fix(release):** Resolve combo prefixing, Electron packaging, CLI auth, and release-branch integration regressions. (#1471, #1492, #1496, #1497, #1486) +- **fix(providers):** Resolve 400 errors for GLM and Antigravity Claude adapter during request translation by scoping prompt caching to compatible Anthropic endpoints and flattening system instructions. (#1514, #1520, #1522) +- **fix(core):** Strip `reasoning_content` from OpenAI format messages for non-reasoning models to prevent upstream HTTP 400 validation errors. (#1505) +- **fix(sse):** Map Claude `output_config/thinking` to OpenAI `reasoning_effort` for proper Antigravity tool translation. (#1528) +- **fix(combo):** Fallback to next model on all-accounts-rate-limited (HTTP 503/429) to maintain high availability. (#1523) +- **fix(api):** Harden batch and file endpoints for auth and recovery to prevent schema state collisions. +- **fix(ui):** Add missing UI wiring for "Add Memory" and "Import" buttons on the `/dashboard/memory` page. (#1506) +- **fix(ui):** Prevent Dark Mode FOUC (Flash of Unstyled Content) by injecting a synchronous theme initialization script into the root `layout.tsx`. +- **fix(ui):** Fix mobile layout text overflow in provider and combo cards, and enable touch-friendly reordering arrows across all combo strategies. +- **fix(core):** Add periodic runtime log rotation checks to prevent disk exhaustion in long-running instances. (#1504 — thanks @ether-btc) +- **fix(build):** Resolve missing `process` module in webpack client build for pino-abstract-transport. (#1509 — thanks @hartmark) +- **fix(ui):** Add dark mode support for native dropdown `