From 0cd388efb8fa1fc206c8bca53e1e76a2e0adf549 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Tue, 28 Apr 2026 20:46:25 -0300 Subject: [PATCH] Release v3.7.4 (#1730) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(release): v3.7.4 — version bump, openapi and changelog sync * fix: preserve previous_response_id and conversation_id fields on empty input array (#1729) * fix: bypass UI validation block for optional API keys and fix string fallback typing (#1721) * fix(proxy): disable HTTP keep-alive and pipelining in Undici proxy dispatcher to prevent socket hang up * feat(proxy): implement bulk proxy import via pipe-delimited parser with update-or-create logic * docs: update changelog for v3.7.4 fixes and proxy features * test: update responses store expectations for empty input arrays * feat(pwa): add fullscreen installable PWA with manifest, service worker, and cross-platform app icons. (#1728) Integrated into release/v3.7.4 * Fix image provider validation and Stability image requests (#1726) Integrated into release/v3.7.4 * docs: add PR 1726 and PR 1728 to v3.7.4 changelog * fix(security): replace insecure Math.random with crypto.getRandomValues for fallback UUID generation * fix(migrations): intercept 007 migration to use IF NOT EXISTS logic on fresh installs Fixes #1733 * test: fix typescript compilation errors in unit tests * fix(db): reconcile legacy reasoning cache migration * chore(release): bump to v3.7.4 — changelog, docs, version sync * fix(cc-compatible): preserve Claude Code system skeleton (#1740) Integrated into release/v3.7.4 * docs(changelog): update for PR #1740 merge * docs(changelog): include workflow updates * fix(db): reconcile legacy reasoning cache migration (#1734) Integrated into release/v3.7.4 * Add endpoint tunnel visibility settings (#1743) Integrated into release/v3.7.4 * Normalize max reasoning effort for Codex routing (#1744) Integrated into release/v3.7.4 * Fix Claude Code gateway config helper (#1745) Integrated into release/v3.7.4 * Refresh CLI fingerprint provider profiles (#1746) Integrated into release/v3.7.4 * Integrated into release/v3.7.4 (PR #1742) * docs(changelog): update for PRs 1742-1746 --------- Co-authored-by: diegosouzapw Co-authored-by: Yash Ghule Co-authored-by: backryun Co-authored-by: dhaern Co-authored-by: Randi <55005611+rdself@users.noreply.github.com> Co-authored-by: Duncan L --- .env.example | 4 + CHANGELOG.md | 36 + docs/CLI-TOOLS.md | 24 +- docs/ENVIRONMENT.md | 7 +- docs/USER_GUIDE.md | 10 +- docs/i18n/ar/CHANGELOG.md | 34 +- docs/i18n/bg/CHANGELOG.md | 34 +- docs/i18n/bn/CHANGELOG.md | 34 +- docs/i18n/cs/CHANGELOG.md | 34 +- docs/i18n/da/CHANGELOG.md | 34 +- docs/i18n/de/CHANGELOG.md | 34 +- docs/i18n/es/CHANGELOG.md | 34 +- docs/i18n/fa/CHANGELOG.md | 34 +- docs/i18n/fi/CHANGELOG.md | 34 +- docs/i18n/fr/CHANGELOG.md | 34 +- docs/i18n/gu/CHANGELOG.md | 34 +- docs/i18n/he/CHANGELOG.md | 34 +- docs/i18n/hi/CHANGELOG.md | 34 +- docs/i18n/hu/CHANGELOG.md | 34 +- docs/i18n/id/CHANGELOG.md | 34 +- docs/i18n/it/CHANGELOG.md | 34 +- docs/i18n/ja/CHANGELOG.md | 34 +- docs/i18n/ko/CHANGELOG.md | 34 +- docs/i18n/mr/CHANGELOG.md | 34 +- docs/i18n/ms/CHANGELOG.md | 34 +- docs/i18n/nl/CHANGELOG.md | 34 +- docs/i18n/no/CHANGELOG.md | 34 +- docs/i18n/phi/CHANGELOG.md | 34 +- docs/i18n/pl/CHANGELOG.md | 34 +- docs/i18n/pt-BR/CHANGELOG.md | 34 +- docs/i18n/pt/CHANGELOG.md | 34 +- docs/i18n/ro/CHANGELOG.md | 34 +- docs/i18n/ru/CHANGELOG.md | 34 +- docs/i18n/sk/CHANGELOG.md | 34 +- docs/i18n/sv/CHANGELOG.md | 34 +- docs/i18n/sw/CHANGELOG.md | 34 +- docs/i18n/ta/CHANGELOG.md | 34 +- docs/i18n/te/CHANGELOG.md | 34 +- docs/i18n/th/CHANGELOG.md | 34 +- docs/i18n/tr/CHANGELOG.md | 34 +- docs/i18n/uk-UA/CHANGELOG.md | 34 +- docs/i18n/ur/CHANGELOG.md | 34 +- docs/i18n/vi/CHANGELOG.md | 34 +- docs/i18n/zh-CN/CHANGELOG.md | 34 +- docs/openapi.yaml | 2 +- electron/package.json | 2 +- llm.txt | 4 +- open-sse/config/cliFingerprints.ts | 34 +- open-sse/config/providerHeaderProfiles.ts | 70 +- open-sse/executors/antigravity.ts | 41 +- open-sse/executors/base.ts | 2 +- open-sse/executors/codex.ts | 25 +- open-sse/package.json | 2 +- open-sse/services/claudeCodeCompatible.ts | 24 +- open-sse/services/thinkingBudget.ts | 5 +- .../translator/request/claude-to-openai.ts | 12 +- .../translator/request/openai-responses.ts | 7 +- open-sse/utils/cursorVersionDetector.ts | 2 +- open-sse/utils/proxyDispatcher.ts | 33 +- open-sse/utils/streamReadiness.ts | 26 +- package-lock.json | 1174 ++++++++++++++++- package.json | 3 +- public/apple-touch-icon.png | Bin 0 -> 7230 bytes public/favicon.ico | Bin 0 -> 141845 bytes public/icon-512.png | Bin 0 -> 7230 bytes public/sw.js | 77 ++ .../(dashboard)/dashboard/HomePageClient.tsx | 90 +- src/app/(dashboard)/dashboard/agents/page.tsx | 35 +- .../changelog/components/ChangelogViewer.tsx | 146 ++ .../changelog/components/NewsViewer.tsx | 95 ++ .../(dashboard)/dashboard/changelog/page.tsx | 40 + .../cli-tools/components/ClaudeToolCard.tsx | 34 +- .../dashboard/endpoint/EndpointPageClient.tsx | 454 +++---- .../dashboard/providers/[id]/page.tsx | 73 +- .../(dashboard)/dashboard/providers/page.tsx | 49 +- .../settings/components/AppearanceTab.tsx | 56 + .../components/ProxyRegistryManager.tsx | 342 +++++ .../api/cli-tools/claude-settings/route.ts | 10 +- .../api/settings/proxies/bulk-import/route.ts | 75 ++ src/app/api/system/version/route.ts | 24 +- src/app/api/v1/images/edits/route.ts | 33 +- src/app/layout.tsx | 28 +- src/app/manifest.ts | 29 + src/i18n/messages/ar.json | 3 +- src/i18n/messages/bg.json | 3 +- src/i18n/messages/bn.json | 3 +- src/i18n/messages/cs.json | 3 +- src/i18n/messages/da.json | 3 +- src/i18n/messages/de.json | 3 +- src/i18n/messages/en.json | 88 +- src/i18n/messages/es.json | 3 +- src/i18n/messages/fa.json | 3 +- src/i18n/messages/fi.json | 3 +- src/i18n/messages/fr.json | 3 +- src/i18n/messages/gu.json | 3 +- src/i18n/messages/he.json | 3 +- src/i18n/messages/hi.json | 3 +- src/i18n/messages/hu.json | 3 +- src/i18n/messages/id.json | 3 +- src/i18n/messages/in.json | 3 +- src/i18n/messages/it.json | 3 +- src/i18n/messages/ja.json | 3 +- src/i18n/messages/ko.json | 3 +- src/i18n/messages/mr.json | 3 +- src/i18n/messages/ms.json | 3 +- src/i18n/messages/nl.json | 3 +- src/i18n/messages/no.json | 3 +- src/i18n/messages/phi.json | 3 +- src/i18n/messages/pl.json | 3 +- src/i18n/messages/pt-BR.json | 3 +- src/i18n/messages/pt.json | 3 +- src/i18n/messages/ro.json | 3 +- src/i18n/messages/ru.json | 3 +- src/i18n/messages/sk.json | 3 +- src/i18n/messages/sv.json | 3 +- src/i18n/messages/sw.json | 3 +- src/i18n/messages/ta.json | 3 +- src/i18n/messages/te.json | 3 +- src/i18n/messages/th.json | 3 +- src/i18n/messages/tr.json | 3 +- src/i18n/messages/uk-UA.json | 3 +- src/i18n/messages/ur.json | 3 +- src/i18n/messages/vi.json | 3 +- src/i18n/messages/zh-CN.json | 67 +- src/lib/db/migrationRunner.ts | 22 + src/lib/db/proxies.ts | 26 + src/lib/db/settings.ts | 2 + src/lib/localDb.ts | 1 + src/lib/oauth/constants/oauth.ts | 2 +- src/shared/components/PwaRegister.tsx | 17 + src/shared/constants/cliCompatProviders.ts | 64 +- src/shared/constants/sidebarVisibility.ts | 2 + src/shared/services/claudeCliConfig.ts | 17 + src/shared/utils/cliCompat.ts | 3 + src/shared/utils/machineId.ts | 36 +- src/shared/utils/releaseNotes.ts | 53 + src/shared/validation/schemas.ts | 9 + src/shared/validation/settingsSchemas.ts | 2 + src/types/settings.ts | 2 + .../unit/anthropic-cache-fingerprint.test.ts | 2 +- tests/unit/cc-compatible-provider.test.ts | 14 +- tests/unit/claude-cli-config.test.ts | 31 + .../claude-code-compatible-request.test.ts | 38 +- tests/unit/cli-tools.test.ts | 79 +- tests/unit/config-hot-reload.test.ts | 6 +- tests/unit/cursor-version-detector.test.mjs | 2 +- tests/unit/db-migration-runner.test.ts | 59 + tests/unit/executor-antigravity.test.ts | 54 +- tests/unit/executor-codex.test.ts | 25 +- tests/unit/image-generation-route.test.ts | 27 + tests/unit/provider-header-profiles.test.ts | 36 +- tests/unit/qoder-executor.test.ts | 5 +- tests/unit/release-notes.test.ts | 52 + tests/unit/responses-handler.test.ts | 27 +- tests/unit/settings-api.test.ts | 23 +- tests/unit/sidebar-visibility.test.ts | 23 + tests/unit/thinking-budget.test.ts | 3 +- .../unit/translator-claude-to-openai.test.ts | 15 +- .../translator-openai-responses-req.test.ts | 15 + tests/unit/usage-service-hardening.test.ts | 10 +- 160 files changed, 4957 insertions(+), 684 deletions(-) create mode 100644 public/apple-touch-icon.png create mode 100644 public/favicon.ico create mode 100644 public/icon-512.png create mode 100644 public/sw.js create mode 100644 src/app/(dashboard)/dashboard/changelog/components/ChangelogViewer.tsx create mode 100644 src/app/(dashboard)/dashboard/changelog/components/NewsViewer.tsx create mode 100644 src/app/(dashboard)/dashboard/changelog/page.tsx create mode 100644 src/app/api/settings/proxies/bulk-import/route.ts create mode 100644 src/app/manifest.ts create mode 100644 src/shared/components/PwaRegister.tsx create mode 100644 src/shared/services/claudeCliConfig.ts create mode 100644 src/shared/utils/cliCompat.ts create mode 100644 src/shared/utils/releaseNotes.ts create mode 100644 tests/unit/claude-cli-config.test.ts create mode 100644 tests/unit/release-notes.test.ts diff --git a/.env.example b/.env.example index eb3dc31fc4..e9992bfb91 100644 --- a/.env.example +++ b/.env.example @@ -705,6 +705,10 @@ APP_LOG_TO_FILE=true # ── CC-compatible provider (experimental) ── # Enable the Claude Code compatible provider endpoint. +# This is only for third-party relays that accept Claude Code clients exclusively. +# OmniRoute rewrites requests to pass those relays' Claude Code client validation. +# If you only want to use Claude Code CLI, or you are not sure what these relays are, +# keep this disabled and add a regular Anthropic-compatible provider instead. # Used by: src/shared/utils/featureFlags.ts # ENABLE_CC_COMPATIBLE_PROVIDER=false diff --git a/CHANGELOG.md b/CHANGELOG.md index 96c734486c..d829a062b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,42 @@ --- +## [3.7.4] — 2026-04-28 + +### ✨ New Features + +- **feat(ui):** add endpoint tunnel visibility settings (#1743) +- **feat(cli):** refresh CLI fingerprint provider profiles (#1746) +- **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table +- **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) + +### 🔒 Security + +- **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) + +### 🐛 Bug Fixes + +- **fix(cc-compatible):** fix CC-compatible relay format and UI copy (#1742) +- **fix(codex):** normalize max reasoning effort for Codex routing (#1744) +- **fix(claude-code):** fix Claude Code gateway config helper (#1745) +- **fix(db):** reconcile legacy `create_reasoning_cache` migration tracking to prevent version shadowing on `032` and resolve startup warnings (#1734) +- **fix(db):** intercept `007` migration to use idempotent `IF NOT EXISTS` logic via `PRAGMA table_info`, preventing syntax crashes on fresh installs (#1733) +- **fix(cc-compatible):** preserve Claude Code system skeleton to prevent request rejection by strict compatible upstream providers (#1740) + +- **fix(providers):** add API key validation for image-only providers and fix Stability AI requests to use `multipart/form-data` instead of JSON (#1726) +- **fix(codex):** preserve `previous_response_id` and `conversation_id` fields when input array is empty to prevent schema validation errors (#1729) +- **fix(searxng):** bypass UI validation block when `apiKeyOptional` is true and fix typing errors in provider dashboard to allow saving search providers without credentials (#1721) +- **fix(proxy):** disable HTTP keep-alive and pipelining in Undici proxy dispatcher to prevent "Socket hang up" rotation failures +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +### 🛠️ Maintenance + +- **workflow:** add phase 4 release monitoring instructions to `/generate-release` workflow +- **test:** fix typescript compilation errors in unit tests to keep CI typecheck pipeline fully green +- **test:** update responses store expectations for empty input arrays + +--- + ## [3.7.3] — 2026-04-28 ### 🐛 Bug Fixes diff --git a/docs/CLI-TOOLS.md b/docs/CLI-TOOLS.md index bda30bd231..f263563759 100644 --- a/docs/CLI-TOOLS.md +++ b/docs/CLI-TOOLS.md @@ -121,8 +121,8 @@ Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`: # OmniRoute Universal Endpoint export OPENAI_BASE_URL="http://localhost:20128/v1" export OPENAI_API_KEY="sk-your-omniroute-key" -export ANTHROPIC_BASE_URL="http://localhost:20128/v1" -export ANTHROPIC_API_KEY="sk-your-omniroute-key" +export ANTHROPIC_BASE_URL="http://localhost:20128" +export ANTHROPIC_AUTH_TOKEN="sk-your-omniroute-key" export GEMINI_BASE_URL="http://localhost:20128/v1" export GEMINI_API_KEY="sk-your-omniroute-key" ``` @@ -137,18 +137,19 @@ export GEMINI_API_KEY="sk-your-omniroute-key" ### Claude Code ```bash -# Via CLI: -claude config set --global api-base-url http://localhost:20128/v1 - -# Or create ~/.claude/settings.json: +# Create ~/.claude/settings.json: mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF { - "apiBaseUrl": "http://localhost:20128/v1", - "apiKey": "sk-your-omniroute-key" + "env": { + "ANTHROPIC_BASE_URL": "http://localhost:20128", + "ANTHROPIC_AUTH_TOKEN": "sk-your-omniroute-key" + } } EOF ``` +Use the unified Anthropic gateway root for Claude Code. Do not append `/v1` here. + **Test:** `claude "say hello"` --- @@ -370,6 +371,7 @@ They run as internal routes and use OmniRoute's model routing automatically. ```bash # Install all CLIs and configure for OmniRoute (replace with your key and server URL) OMNIROUTE_URL="http://localhost:20128/v1" +OMNIROUTE_ANTHROPIC_URL="http://localhost:20128" OMNIROUTE_KEY="sk-your-omniroute-key" npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode @qwen-code/qwen-code @@ -380,13 +382,13 @@ apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | # Write configs mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue -cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}" +cat > ~/.claude/settings.json <<< "{\"env\":{\"ANTHROPIC_BASE_URL\":\"$OMNIROUTE_ANTHROPIC_URL\",\"ANTHROPIC_AUTH_TOKEN\":\"$OMNIROUTE_KEY\"}}" cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL" cat >> ~/.bashrc << EOF export OPENAI_BASE_URL="$OMNIROUTE_URL" export OPENAI_API_KEY="$OMNIROUTE_KEY" -export ANTHROPIC_BASE_URL="$OMNIROUTE_URL" -export ANTHROPIC_API_KEY="$OMNIROUTE_KEY" +export ANTHROPIC_BASE_URL="$OMNIROUTE_ANTHROPIC_URL" +export ANTHROPIC_AUTH_TOKEN="$OMNIROUTE_KEY" EOF source ~/.bashrc diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index fddc751655..02e7c2843b 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -541,12 +541,17 @@ Automatic model pricing data synchronization from external sources. | `CLOUDFLARED_BIN` | auto-detect | `src/lib/cloudflaredTunnel.ts` | Custom path to `cloudflared` binary. | | `SEARCH_CACHE_TTL_MS` | `300000` (5 min) | `open-sse/services/searchCache.ts` | TTL for search API (Perplexity, Brave, etc.) response caching. | | `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` | `false` | `src/app/api/providers/route.ts` | Allow multiple simultaneous connections per OpenAI-compatible provider. | -| `ENABLE_CC_COMPATIBLE_PROVIDER` | `false` | `src/shared/utils/featureFlags.ts` | Enable experimental Claude Code compatible provider endpoint. | +| `ENABLE_CC_COMPATIBLE_PROVIDER` | `false` | `src/shared/utils/featureFlags.ts` | Reveal the experimental CC-compatible provider UI for Claude Code-only relays. | | `CLIPROXYAPI_HOST` | `127.0.0.1` | `open-sse/executors/cliproxyapi.ts` | CLIProxyAPI bridge host (legacy integration). | | `CLIPROXYAPI_PORT` | `5544` | `open-sse/executors/cliproxyapi.ts` | CLIProxyAPI bridge port. | | `CLIPROXYAPI_CONFIG_DIR` | `~/.cli-proxy-api` | `src/lib/versionManager/processManager.ts` | CLIProxyAPI config directory. | | `LOCAL_HOSTNAMES` | _(empty)_ | `open-sse/config/providerRegistry.ts` | Comma-separated additional hostnames treated as "local" (Docker service names, etc.). | +`ENABLE_CC_COMPATIBLE_PROVIDER` is only for third-party relays that accept Claude Code clients +exclusively. OmniRoute rewrites requests so those relays accept them. If you only want to use +Claude Code CLI, or you are not sure what these relays are, keep this disabled and add a regular +Anthropic-compatible provider instead. + --- ## 21. Proxy Health diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md index 4b076e1d00..1ea97b1278 100644 --- a/docs/USER_GUIDE.md +++ b/docs/USER_GUIDE.md @@ -272,15 +272,19 @@ Settings → Models → Advanced: ### Claude Code -Edit `~/.claude/config.json`: +Edit `~/.claude/settings.json`: ```json { - "anthropic_api_base": "http://localhost:20128/v1", - "anthropic_api_key": "your-omniroute-api-key" + "env": { + "ANTHROPIC_BASE_URL": "http://localhost:20128", + "ANTHROPIC_AUTH_TOKEN": "your-omniroute-api-key" + } } ``` +Use the Claude-compatible root endpoint here. Do not append `/v1` to `ANTHROPIC_BASE_URL`. + ### Codex CLI ```bash diff --git a/docs/i18n/ar/CHANGELOG.md b/docs/i18n/ar/CHANGELOG.md index 5d1bff48ed..2f84624023 100644 --- a/docs/i18n/ar/CHANGELOG.md +++ b/docs/i18n/ar/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/bg/CHANGELOG.md b/docs/i18n/bg/CHANGELOG.md index 6b7682092e..532214bb70 100644 --- a/docs/i18n/bg/CHANGELOG.md +++ b/docs/i18n/bg/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/bn/CHANGELOG.md b/docs/i18n/bn/CHANGELOG.md index 35b0c6d20d..2a1f4023d1 100644 --- a/docs/i18n/bn/CHANGELOG.md +++ b/docs/i18n/bn/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/cs/CHANGELOG.md b/docs/i18n/cs/CHANGELOG.md index 068b2112c1..7b59dcdd81 100644 --- a/docs/i18n/cs/CHANGELOG.md +++ b/docs/i18n/cs/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/da/CHANGELOG.md b/docs/i18n/da/CHANGELOG.md index df2bdece33..5ac55da9b4 100644 --- a/docs/i18n/da/CHANGELOG.md +++ b/docs/i18n/da/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/de/CHANGELOG.md b/docs/i18n/de/CHANGELOG.md index 49897fdd31..f5814bcd58 100644 --- a/docs/i18n/de/CHANGELOG.md +++ b/docs/i18n/de/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/es/CHANGELOG.md b/docs/i18n/es/CHANGELOG.md index bed84623fa..ae27b1a6cc 100644 --- a/docs/i18n/es/CHANGELOG.md +++ b/docs/i18n/es/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/fa/CHANGELOG.md b/docs/i18n/fa/CHANGELOG.md index 13ea7e5911..a3a52dc001 100644 --- a/docs/i18n/fa/CHANGELOG.md +++ b/docs/i18n/fa/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/fi/CHANGELOG.md b/docs/i18n/fi/CHANGELOG.md index bb093ded7f..d4f07a7e00 100644 --- a/docs/i18n/fi/CHANGELOG.md +++ b/docs/i18n/fi/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/fr/CHANGELOG.md b/docs/i18n/fr/CHANGELOG.md index 59df590135..81e86bbc05 100644 --- a/docs/i18n/fr/CHANGELOG.md +++ b/docs/i18n/fr/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/gu/CHANGELOG.md b/docs/i18n/gu/CHANGELOG.md index 4f7e6146aa..0bbee5d7f8 100644 --- a/docs/i18n/gu/CHANGELOG.md +++ b/docs/i18n/gu/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/he/CHANGELOG.md b/docs/i18n/he/CHANGELOG.md index 135eadfcc6..1651d8eb2d 100644 --- a/docs/i18n/he/CHANGELOG.md +++ b/docs/i18n/he/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/hi/CHANGELOG.md b/docs/i18n/hi/CHANGELOG.md index 10a9fdb26c..9ea77a070e 100644 --- a/docs/i18n/hi/CHANGELOG.md +++ b/docs/i18n/hi/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/hu/CHANGELOG.md b/docs/i18n/hu/CHANGELOG.md index 67f3ef3cc4..f11a2c90b6 100644 --- a/docs/i18n/hu/CHANGELOG.md +++ b/docs/i18n/hu/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/id/CHANGELOG.md b/docs/i18n/id/CHANGELOG.md index 87aed59ee4..0f0fb403f5 100644 --- a/docs/i18n/id/CHANGELOG.md +++ b/docs/i18n/id/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/it/CHANGELOG.md b/docs/i18n/it/CHANGELOG.md index 2af1fbb7bb..4db3a1f2f2 100644 --- a/docs/i18n/it/CHANGELOG.md +++ b/docs/i18n/it/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/ja/CHANGELOG.md b/docs/i18n/ja/CHANGELOG.md index 86b42fa60d..9447f5cf1b 100644 --- a/docs/i18n/ja/CHANGELOG.md +++ b/docs/i18n/ja/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/ko/CHANGELOG.md b/docs/i18n/ko/CHANGELOG.md index 03fb452bf8..b85ba72008 100644 --- a/docs/i18n/ko/CHANGELOG.md +++ b/docs/i18n/ko/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/mr/CHANGELOG.md b/docs/i18n/mr/CHANGELOG.md index 98e9c5907d..f59c86f893 100644 --- a/docs/i18n/mr/CHANGELOG.md +++ b/docs/i18n/mr/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/ms/CHANGELOG.md b/docs/i18n/ms/CHANGELOG.md index 04f8e66d2e..76d7f52c87 100644 --- a/docs/i18n/ms/CHANGELOG.md +++ b/docs/i18n/ms/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/nl/CHANGELOG.md b/docs/i18n/nl/CHANGELOG.md index dc3a8ac997..2edeab924f 100644 --- a/docs/i18n/nl/CHANGELOG.md +++ b/docs/i18n/nl/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/no/CHANGELOG.md b/docs/i18n/no/CHANGELOG.md index 33edd30b68..5508badcfd 100644 --- a/docs/i18n/no/CHANGELOG.md +++ b/docs/i18n/no/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/phi/CHANGELOG.md b/docs/i18n/phi/CHANGELOG.md index d917dd537a..79df01ab9c 100644 --- a/docs/i18n/phi/CHANGELOG.md +++ b/docs/i18n/phi/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/pl/CHANGELOG.md b/docs/i18n/pl/CHANGELOG.md index eaaf4e6040..449d906a62 100644 --- a/docs/i18n/pl/CHANGELOG.md +++ b/docs/i18n/pl/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/pt-BR/CHANGELOG.md b/docs/i18n/pt-BR/CHANGELOG.md index 4c783165b0..c2a65d5855 100644 --- a/docs/i18n/pt-BR/CHANGELOG.md +++ b/docs/i18n/pt-BR/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/pt/CHANGELOG.md b/docs/i18n/pt/CHANGELOG.md index 922f92eb2d..f57dc3fd71 100644 --- a/docs/i18n/pt/CHANGELOG.md +++ b/docs/i18n/pt/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/ro/CHANGELOG.md b/docs/i18n/ro/CHANGELOG.md index 5f7d058fcc..64ecea4f27 100644 --- a/docs/i18n/ro/CHANGELOG.md +++ b/docs/i18n/ro/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/ru/CHANGELOG.md b/docs/i18n/ru/CHANGELOG.md index 01d695da50..17252b3e41 100644 --- a/docs/i18n/ru/CHANGELOG.md +++ b/docs/i18n/ru/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/sk/CHANGELOG.md b/docs/i18n/sk/CHANGELOG.md index 96a42b609a..9ba25a9c88 100644 --- a/docs/i18n/sk/CHANGELOG.md +++ b/docs/i18n/sk/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/sv/CHANGELOG.md b/docs/i18n/sv/CHANGELOG.md index 06d09439fe..e5a2cf37c5 100644 --- a/docs/i18n/sv/CHANGELOG.md +++ b/docs/i18n/sv/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/sw/CHANGELOG.md b/docs/i18n/sw/CHANGELOG.md index 436b5e0a7f..a9f6058daf 100644 --- a/docs/i18n/sw/CHANGELOG.md +++ b/docs/i18n/sw/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/ta/CHANGELOG.md b/docs/i18n/ta/CHANGELOG.md index d960f7dccd..acb416710e 100644 --- a/docs/i18n/ta/CHANGELOG.md +++ b/docs/i18n/ta/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/te/CHANGELOG.md b/docs/i18n/te/CHANGELOG.md index 28cf1383cb..2b31e03d3e 100644 --- a/docs/i18n/te/CHANGELOG.md +++ b/docs/i18n/te/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/th/CHANGELOG.md b/docs/i18n/th/CHANGELOG.md index e7072e3ef4..671a5c9493 100644 --- a/docs/i18n/th/CHANGELOG.md +++ b/docs/i18n/th/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/tr/CHANGELOG.md b/docs/i18n/tr/CHANGELOG.md index 76d74c3559..728d8d3411 100644 --- a/docs/i18n/tr/CHANGELOG.md +++ b/docs/i18n/tr/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/uk-UA/CHANGELOG.md b/docs/i18n/uk-UA/CHANGELOG.md index 76f7e70588..da8f950918 100644 --- a/docs/i18n/uk-UA/CHANGELOG.md +++ b/docs/i18n/uk-UA/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/ur/CHANGELOG.md b/docs/i18n/ur/CHANGELOG.md index 6d5b5d9acf..198881b9b8 100644 --- a/docs/i18n/ur/CHANGELOG.md +++ b/docs/i18n/ur/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/vi/CHANGELOG.md b/docs/i18n/vi/CHANGELOG.md index 46653db7bc..09c3dbec2d 100644 --- a/docs/i18n/vi/CHANGELOG.md +++ b/docs/i18n/vi/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/i18n/zh-CN/CHANGELOG.md b/docs/i18n/zh-CN/CHANGELOG.md index 30a0a503e7..b98fb404b2 100644 --- a/docs/i18n/zh-CN/CHANGELOG.md +++ b/docs/i18n/zh-CN/CHANGELOG.md @@ -4,12 +4,39 @@ --- - ## [Unreleased] --- -## [3.7.2] — 2026-04-27 +## [3.7.4] — 2026-04-28 + +### 🐛 Bug Fixes + +- **stream:** correctly identify `thought` and `error` blocks in Antigravity/Gemini SSE streams to prevent premature 502 timeouts (#1725, #1705) + +--- + +## [3.7.3] — 2026-04-28 + +### 🐛 Bug Fixes + +- **fix(claude):** strip existing billing headers from system array before injecting to prevent Anthropic prompt cache misses — stacked `x-anthropic-billing-header` blocks invalidated prefix matching, causing ~100% cache_create instead of cache_read (#1712) +- **fix(claude):** strip `output_config.format` for non-Anthropic Claude-compatible providers during passthrough — third-party Claude endpoints (MiniMax, DeepSeek via aggregators) reject structured output fields with 400 errors (#1719) +- **fix(combo):** set terminal error state on response quality validation failure — prevents misleading `ALL_ACCOUNTS_INACTIVE` 503 when the real issue is response quality validation (#1707, #1710) +- **fix(combo):** treat combo fallback as target-level orchestration — all non-ok responses (including generic 400s) now fall through to the next target instead of being terminal; removes complex bad-request allowlist regex (#1713) +- **fix(codex):** restore namespace MCP tools and hosted-tool whitelist — regression from #1581 that silently dropped all MCP tool groups and Responses-API hosted tools (#1715) +- **fix(codex):** add neutral instructions for bare chat requests — Codex Responses backend rejects requests without `instructions`, making Codex unusable for normal chat (#1709) +- **fix(proxy):** wrap proxy assignment queries in try-catch for missing `proxy_assignments` table — Electron installs where migration 004 hasn't run no longer crash with `no such table` error (#1706) +- **fix(migration):** improve Windows file URL path resolution in migration runner — adds direct URL path extraction and `process.cwd()` fallback for CI-built bundles with leaked build-time paths (#1704) +- **fix(ui):** fix light mode active request payload modal — add missing `--color-card` theme token, use opaque `bg-surface` instead of translucent `bg-card/70`, add backdrop blur (#1714) + +### 🔄 Updates + +- **chore(image-models):** refresh image generation model registry — replace stale FLUX aliases with FLUX Kontext / FLUX.2 mappings, remove deprecated FLUX Redux/Depth/Canny variants (#1722) + +--- + +## [3.7.2] — 2026-04-28 ### ✨ New Features @@ -30,6 +57,9 @@ - **fix(stream):** fail zombie SSE streams before accepting response — returns 504 instead of hanging indefinitely, enables combo fallback (#1693) - **fix(combo):** complete context truncation hotfix — cache getCombos() with 10s TTL, pass allCombosData to resolveComboTargets() for nested combo resolution, consolidate duplicated context overflow regex patterns (#1685) - **fix(codex):** raise default quota threshold from 90% to 99% to avoid premature account blocking when usable quota remains (#1697) +- **fix(memory):** use `user` role for GLM/ZAI/Qianfan providers — providers with strict role constraints (no `system` role) now correctly receive memory context as a `user` message instead of a `system` message, preventing 422 validation errors (#1701) +- **fix(oauth):** target specific connection by ID on re-auth token exchange — prevents duplicate account creation when re-authenticating an existing OAuth connection (#1702 — thanks @namhhitvn) +- **feat(email-privacy):** integrate email visibility toggle in RequestLoggerV2 — log detail modal now respects global email privacy state, hiding email addresses by default (#1700 — thanks @namhhitvn) - **fix(combo):** trigger fallback on Anthropic `Invalid signature in thinking block` errors instead of returning 400 directly (#1696) - **fix:** combo retry loop stops immediately on client disconnect (499) (#1681) - **fix(search):** support optional bearer auth for SearXNG (#1683) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 8d05e65cd2..ccf1626744 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: title: OmniRoute API - version: 3.7.3 + version: 3.7.4 description: | OmniRoute is a local-first AI API proxy router. It provides an OpenAI-compatible endpoint that routes requests to multiple AI providers with load balancing, diff --git a/electron/package.json b/electron/package.json index 1950cbfc25..7a023263f8 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,6 +1,6 @@ { "name": "omniroute-desktop", - "version": "3.7.3", + "version": "3.7.4", "description": "OmniRoute Desktop Application", "main": "main.js", "author": { diff --git a/llm.txt b/llm.txt index 92e9d0c59b..99ba91f792 100644 --- a/llm.txt +++ b/llm.txt @@ -8,7 +8,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo **Key value:** One endpoint (`http://localhost:20128/v1`), unlimited models, zero downtime, minimal cost. -**Current version:** 3.7.3 +**Current version:** 3.7.4 ## Tech Stack @@ -279,7 +279,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo └── .env.example # Environment variable template ``` -## Key Features (v3.7.3) +## Key Features (v3.7.4) ### Core Proxy - **160+ AI providers** with automatic format translation diff --git a/open-sse/config/cliFingerprints.ts b/open-sse/config/cliFingerprints.ts index a4d4742557..7d7921abf6 100644 --- a/open-sse/config/cliFingerprints.ts +++ b/open-sse/config/cliFingerprints.ts @@ -15,6 +15,7 @@ import { GITHUB_COPILOT_CHAT_USER_AGENT, getQwenOauthHeaders, } from "./providerHeaderProfiles.ts"; +import { normalizeCliCompatProviderId } from "@/shared/utils/cliCompat"; export interface CliFingerprint { /** Ordered list of header names (case-sensitive). Unlisted headers are appended. */ @@ -22,7 +23,7 @@ export interface CliFingerprint { /** Ordered list of top-level JSON body fields. Unlisted fields are appended. */ bodyFieldOrder: string[]; /** User-Agent string to inject (overrides default) */ - userAgent?: string; + userAgent?: string | (() => string); /** Extra headers to add */ extraHeaders?: Record; } @@ -54,7 +55,9 @@ export const CLI_FINGERPRINTS: Record = { "n", "stop", ], - userAgent: "codex-cli", + // Codex builds mode-specific client headers in its executor/config. The CLI fingerprint must + // only preserve ordering here; overriding User-Agent with a generic value would erase the + // executor-provided version or user override. }, claude: { headerOrder: [ @@ -172,8 +175,16 @@ export const CLI_FINGERPRINTS: Record = { "Accept", "Accept-Encoding", ], - bodyFieldOrder: ["project", "model", "userAgent", "requestType", "requestId", "request"], - userAgent: getAntigravityUserAgent(), + bodyFieldOrder: [ + "project", + "model", + "userAgent", + "requestType", + "requestId", + "enabledCreditTypes", + "request", + ], + userAgent: getAntigravityUserAgent, }, qwen: { headerOrder: [ @@ -286,9 +297,10 @@ export function applyFingerprint( headers: Record, body: unknown ): { headers: Record; bodyString: string } { + const normalizedProvider = normalizeCliCompatProviderId(provider || ""); const fingerprintKey = isClaudeCodeCompatible(provider) ? "claude-code-compatible" - : provider?.toLowerCase(); + : normalizedProvider; const fingerprint = CLI_FINGERPRINTS[fingerprintKey]; if (!fingerprint) { @@ -297,7 +309,8 @@ export function applyFingerprint( // Apply user agent override if (fingerprint.userAgent) { - headers["User-Agent"] = fingerprint.userAgent; + headers["User-Agent"] = + typeof fingerprint.userAgent === "function" ? fingerprint.userAgent() : fingerprint.userAgent; } // Apply extra headers @@ -331,7 +344,11 @@ let _cliCompatProviders: Set = new Set(); * Called from the settings API when cliCompatProviders is updated. */ export function setCliCompatProviders(providers: string[]): void { - _cliCompatProviders = new Set((providers || []).map((p) => p.toLowerCase())); + _cliCompatProviders = new Set( + (providers || []) + .map((p) => normalizeCliCompatProviderId(p)) + .filter((provider) => provider in CLI_FINGERPRINTS) + ); } /** @@ -351,7 +368,8 @@ export function isCliCompatEnabled(provider: string): boolean { const key = provider?.toLowerCase().replace(/[^a-z0-9]/g, "_"); // 1. Check runtime cache (set via Settings UI) - if (_cliCompatProviders.has(provider?.toLowerCase())) return true; + const normalizedProvider = normalizeCliCompatProviderId(provider || ""); + if (_cliCompatProviders.has(normalizedProvider)) return true; // 2. Check environment variable: CLI_COMPAT_=1 const envKey = `CLI_COMPAT_${key?.toUpperCase()}`; diff --git a/open-sse/config/providerHeaderProfiles.ts b/open-sse/config/providerHeaderProfiles.ts index fb379ed6b1..301053cb04 100644 --- a/open-sse/config/providerHeaderProfiles.ts +++ b/open-sse/config/providerHeaderProfiles.ts @@ -11,26 +11,22 @@ export const GITHUB_COPILOT_OPENAI_INTENT = "conversation-panel"; export const GITHUB_COPILOT_DEFAULT_INITIATOR = "user"; export const GITHUB_COPILOT_USER_AGENT_LIBRARY = "electron-fetch"; -export const QWEN_CLI_USER_AGENT = "QwenCode/0.15.3 (linux; x64)"; -export const QWEN_STAINLESS_ARCH = "x64"; +export const QWEN_CLI_VERSION = "0.15.4"; export const QWEN_STAINLESS_LANG = "js"; -export const QWEN_STAINLESS_OS = "Linux"; export const QWEN_STAINLESS_PACKAGE_VERSION = "5.11.0"; export const QWEN_STAINLESS_RETRY_COUNT = "1"; export const QWEN_STAINLESS_RUNTIME = "node"; -export const QWEN_STAINLESS_RUNTIME_VERSION = "v18.19.1"; export const QWEN_ACCEPT_LANGUAGE = "*"; export const QWEN_SEC_FETCH_MODE = "cors"; export const QODER_DEFAULT_USER_AGENT = "Qoder-Cli"; -export const QODER_DASHSCOPE_COMPAT_USER_AGENT = "QwenCode/0.15.3 (linux; x64)"; export const KIRO_SDK_USER_AGENT = "AWS-SDK-JS/3.0.0 kiro-ide/1.0.0"; export const KIRO_AMZ_USER_AGENT = "aws-sdk-js/3.0.0 kiro-ide/1.0.0"; export const KIRO_STREAMING_TARGET = "AmazonCodeWhispererStreamingService.GenerateAssistantResponse"; -export const CURSOR_REGISTRY_VERSION = "3.1.0"; +export const CURSOR_REGISTRY_VERSION = "3.2.14"; export function getGitHubCopilotChatHeaders( accept = "application/json", @@ -50,6 +46,48 @@ export function getGitHubCopilotChatHeaders( }; } +function getRuntimePlatform(): string { + return typeof process !== "undefined" && typeof process.platform === "string" + ? process.platform + : "unknown"; +} + +function getRuntimeArch(): string { + return typeof process !== "undefined" && typeof process.arch === "string" ? process.arch : "unknown"; +} + +function getRuntimeVersion(): string { + return typeof process !== "undefined" && typeof process.version === "string" + ? process.version + : "unknown"; +} + +function normalizeStainlessPlatform(platform: string = getRuntimePlatform()): string { + const normalized = platform.toLowerCase(); + if (normalized.includes("ios")) return "iOS"; + if (normalized === "android") return "Android"; + if (normalized === "darwin") return "MacOS"; + if (normalized === "win32") return "Windows"; + if (normalized === "freebsd") return "FreeBSD"; + if (normalized === "openbsd") return "OpenBSD"; + if (normalized === "linux") return "Linux"; + return normalized ? `Other:${normalized}` : "Unknown"; +} + +function normalizeStainlessArch(arch: string = getRuntimeArch()): string { + if (arch === "x32") return "x32"; + if (arch === "x86_64" || arch === "x64") return "x64"; + if (arch === "arm") return "arm"; + if (arch === "aarch64" || arch === "arm64") return "arm64"; + return arch ? `other:${arch}` : "unknown"; +} + +export function getQwenCliUserAgent(version = QWEN_CLI_VERSION): string { + // Qwen Code builds this from the runtime process values. Keep it runtime-derived so + // packaged deployments use their own platform/architecture instead of a maintainer's host. + return `QwenCode/${version} (${getRuntimePlatform()}; ${getRuntimeArch()})`; +} + export function getGitHubCopilotInternalUserHeaders(authorization: string): Record { return { Authorization: authorization, @@ -72,18 +110,19 @@ export function getGitHubCopilotRefreshHeaders(authorization: string): Record { + const userAgent = getQwenCliUserAgent(); return { - "User-Agent": QWEN_CLI_USER_AGENT, + "User-Agent": userAgent, "X-Dashscope-AuthType": "qwen-oauth", "X-Dashscope-CacheControl": "enable", - "X-Dashscope-UserAgent": QWEN_CLI_USER_AGENT, - "X-Stainless-Arch": QWEN_STAINLESS_ARCH, + "X-Dashscope-UserAgent": userAgent, + "X-Stainless-Arch": normalizeStainlessArch(), "X-Stainless-Lang": QWEN_STAINLESS_LANG, - "X-Stainless-Os": QWEN_STAINLESS_OS, + "X-Stainless-Os": normalizeStainlessPlatform(), "X-Stainless-Package-Version": QWEN_STAINLESS_PACKAGE_VERSION, "X-Stainless-Retry-Count": QWEN_STAINLESS_RETRY_COUNT, "X-Stainless-Runtime": QWEN_STAINLESS_RUNTIME, - "X-Stainless-Runtime-Version": QWEN_STAINLESS_RUNTIME_VERSION, + "X-Stainless-Runtime-Version": getRuntimeVersion(), Connection: "keep-alive", "Accept-Language": QWEN_ACCEPT_LANGUAGE, "Sec-Fetch-Mode": QWEN_SEC_FETCH_MODE, @@ -97,14 +136,15 @@ export function getQoderDefaultHeaders(): Record { } export function getQoderDashscopeCompatHeaders(): Record { + const userAgent = getQwenCliUserAgent(); return { "x-dashscope-authtype": "qwen-oauth", "x-dashscope-cachecontrol": "enable", - "user-agent": QODER_DASHSCOPE_COMPAT_USER_AGENT, - "x-dashscope-useragent": QODER_DASHSCOPE_COMPAT_USER_AGENT, - "x-stainless-arch": QWEN_STAINLESS_ARCH, + "user-agent": userAgent, + "x-dashscope-useragent": userAgent, + "x-stainless-arch": normalizeStainlessArch(), "x-stainless-lang": QWEN_STAINLESS_LANG, - "x-stainless-os": QWEN_STAINLESS_OS, + "x-stainless-os": normalizeStainlessPlatform(), }; } diff --git a/open-sse/executors/antigravity.ts b/open-sse/executors/antigravity.ts index 166bb38cb9..9cf0cb989d 100644 --- a/open-sse/executors/antigravity.ts +++ b/open-sse/executors/antigravity.ts @@ -1,5 +1,6 @@ import crypto, { randomUUID } from "crypto"; import { BaseExecutor, mergeUpstreamExtraHeaders, type ExecuteInput } from "./base.ts"; +import { applyFingerprint, isCliCompatEnabled } from "../config/cliFingerprints.ts"; import { PROVIDERS, OAUTH_ENDPOINTS, HTTP_STATUS } from "../config/constants.ts"; import { scrubProxyAndFingerprintHeaders } from "../services/antigravityHeaderScrub.ts"; import { antigravityUserAgent } from "../services/antigravityHeaders.ts"; @@ -27,6 +28,17 @@ const CREDITS_EXHAUSTED_TTL_MS = 5 * 60 * 60 * 1000; // 5 hours const BARE_PRO_IDS = new Set(["gemini-3.1-pro"]); +function serializeAntigravityRequest( + provider: string, + headers: Record, + body: unknown +): { headers: Record; bodyString: string } { + if (!isCliCompatEnabled(provider)) { + return { headers, bodyString: JSON.stringify(body) }; + } + return applyFingerprint(provider, { ...headers }, body); +} + type AntigravityCollectedStream = { textContent: string; finishReason: string; @@ -573,10 +585,13 @@ export class AntigravityExecutor extends BaseExecutor { } try { + const serializedRequest = serializeAntigravityRequest(this.provider, headers, transformedBody); + const finalHeaders = serializedRequest.headers; + const response = await fetch(url, { method: "POST", - headers, - body: JSON.stringify(transformedBody), + headers: finalHeaders, + body: serializedRequest.bodyString, signal, }); @@ -626,11 +641,17 @@ export class AntigravityExecutor extends BaseExecutor { ) { log?.info?.("AG_CREDITS", "Retrying with Google One AI credits"); const creditsBody = injectCreditsField(transformedBody); + const serializedCreditsRequest = serializeAntigravityRequest( + this.provider, + headers, + creditsBody + ); + const finalCreditsHeaders = serializedCreditsRequest.headers; try { const creditsResp = await fetch(url, { method: "POST", - headers, - body: JSON.stringify(creditsBody), + headers: finalCreditsHeaders, + body: serializedCreditsRequest.bodyString, signal, }); if (creditsResp.ok || creditsResp.status !== HTTP_STATUS.RATE_LIMITED) { @@ -640,7 +661,7 @@ export class AntigravityExecutor extends BaseExecutor { creditsResp, model, url, - headers, + finalCreditsHeaders, creditsBody, log, signal @@ -668,7 +689,7 @@ export class AntigravityExecutor extends BaseExecutor { return { response: creditsResp, url, - headers, + headers: finalCreditsHeaders, transformedBody: attachToolNameMap(creditsBody, requestToolNameMap), }; } @@ -769,7 +790,7 @@ export class AntigravityExecutor extends BaseExecutor { return { response: modifiedResponse, url, - headers, + headers: finalHeaders, transformedBody: attachToolNameMap(transformedBody, requestToolNameMap), }; } catch (err) { @@ -785,7 +806,7 @@ export class AntigravityExecutor extends BaseExecutor { response, model, url, - headers, + finalHeaders, transformedBody, log, signal @@ -898,7 +919,7 @@ export class AntigravityExecutor extends BaseExecutor { return { response: tappedResponse, url, - headers, + headers: finalHeaders, transformedBody: attachToolNameMap(transformedBody, requestToolNameMap), }; } @@ -906,7 +927,7 @@ export class AntigravityExecutor extends BaseExecutor { return { response, url, - headers, + headers: finalHeaders, transformedBody: attachToolNameMap(transformedBody, requestToolNameMap), }; } catch (error) { diff --git a/open-sse/executors/base.ts b/open-sse/executors/base.ts index 81cca90907..ada44b7279 100644 --- a/open-sse/executors/base.ts +++ b/open-sse/executors/base.ts @@ -466,7 +466,7 @@ export class BaseExecutor { remapToolNamesInRequest(tb); obfuscateInBody(tb); - const ccVersion = "2.1.114"; + const ccVersion = "2.1.121"; // Fix #1638: Use a stable fingerprint instead of message-derived one. // The original computeFingerprint() hashed first-user-message chars, which // changes every conversation turn. This mutated the system[] prefix on each diff --git a/open-sse/executors/codex.ts b/open-sse/executors/codex.ts index 720930e4d1..42b3049a7f 100644 --- a/open-sse/executors/codex.ts +++ b/open-sse/executors/codex.ts @@ -362,12 +362,16 @@ function convertSystemToDeveloperRole(body: Record): void { * 4. Always deletes previous_response_id (endpoint doesn't persist responses) */ function stripStoredItemReferences(body: Record): void { - // Always strip previous_response_id — the /codex/responses endpoint does not - // persist responses, so any reference to a previous response would cause a 404. - // The official Codex CLI sets previous_response_id to None for HTTP transport. - // Ref: codex-rs codex-api/src/common.rs:187 — previous_response_id: None - // Ref: CLIProxyAPI codex_executor.go:115 — sjson.DeleteBytes(body, "previous_response_id") - delete body.previous_response_id; + const hasInput = Array.isArray(body.input) && body.input.length > 0; + + // Always strip previous_response_id IF we have input. + // The /codex/responses endpoint does not persist responses, so any reference + // to a previous response would cause a 404. However, if input is missing (e.g. Cursor + // trying to continue generation), stripping it leaves the payload empty causing a 400 Schema error. + // We leave it intact so Codex returns 404, which correctly triggers Cursor's fallback to resend history. + if (hasInput) { + delete body.previous_response_id; + } if (!Array.isArray(body.input)) return; @@ -554,6 +558,7 @@ function clampEffort(model: string, requested: string): string { function normalizeEffortValue(value: unknown): string | undefined { if (typeof value !== "string") return undefined; const normalized = value.trim().toLowerCase(); + if (normalized === "max") return "xhigh"; return normalized || undefined; } @@ -1144,9 +1149,13 @@ export class CodexExecutor extends BaseExecutor { // Delete session_id and conversation_id from the body. // These are often injected by OmniRoute's fallback logic for store=true, - // but the upstream Codex API strictly rejects them as unsupported parameters. + // but the upstream Codex API strictly rejects them as unsupported parameters + // UNLESS the request lacks input entirely (where they are required to avoid a 400 Schema Error). delete body.session_id; - delete body.conversation_id; + const hasInput = Array.isArray(body.input) && body.input.length > 0; + if (hasInput) { + delete body.conversation_id; + } if (nativeCodexPassthrough) { return body; diff --git a/open-sse/package.json b/open-sse/package.json index e311fc67fa..4d7bf34fe6 100644 --- a/open-sse/package.json +++ b/open-sse/package.json @@ -1,6 +1,6 @@ { "name": "@omniroute/open-sse", - "version": "3.7.3", + "version": "3.7.4", "description": "Express SSE sidecar for OmniRoute — handles streaming, protocol translation, and provider orchestration", "type": "module", "main": "index.js", diff --git a/open-sse/services/claudeCodeCompatible.ts b/open-sse/services/claudeCodeCompatible.ts index 2c5299ee58..c79a20fc5c 100644 --- a/open-sse/services/claudeCodeCompatible.ts +++ b/open-sse/services/claudeCodeCompatible.ts @@ -249,7 +249,6 @@ export function buildClaudeCodeCompatibleRequest({ messages: normalizedMessages, systemBlocks: effectiveClaudeBody?.system as Record[] | undefined, preserveCacheControl, - injectDefaultSkeleton: !effectiveClaudeBody, }); const resolvedSessionId = sessionId || randomUUID(); const effort = resolveClaudeCodeCompatibleEffort(sourceBody, normalizedBody, model); @@ -550,12 +549,10 @@ function buildClaudeCodeCompatibleSystemBlocks({ messages, systemBlocks, preserveCacheControl, - injectDefaultSkeleton, }: { messages: MessageLike[] | undefined; systemBlocks?: Array> | undefined; preserveCacheControl: boolean; - injectDefaultSkeleton: boolean; }) { const customSystemBlocks = Array.isArray(systemBlocks) && systemBlocks.length > 0 @@ -570,9 +567,9 @@ function buildClaudeCodeCompatibleSystemBlocks({ return preparedBlock; }); - if (!injectDefaultSkeleton) { - return preparedCustomSystemBlocks; - } + const hasDefaultSystemBlock = containsDefaultSystemSkeleton(preparedCustomSystemBlocks); + + if (hasDefaultSystemBlock) return preparedCustomSystemBlocks; return [ ...CLAUDE_CODE_COMPATIBLE_DEFAULT_SYSTEM_BLOCKS.map((block) => ({ ...block })), @@ -580,6 +577,21 @@ function buildClaudeCodeCompatibleSystemBlocks({ ]; } +function containsDefaultSystemSkeleton(blocks: Array>) { + const skeleton = CLAUDE_CODE_COMPATIBLE_DEFAULT_SYSTEM_BLOCKS; + if (skeleton.length === 0) return true; + if (blocks.length < skeleton.length) return false; + + return blocks.some((_, startIndex) => + skeleton.every((defaultBlock, offset) => { + const candidateBlock = blocks[startIndex + offset]; + if (!candidateBlock) return false; + + return Object.entries(defaultBlock).every(([key, value]) => candidateBlock[key] === value); + }) + ); +} + function convertClaudeCodeCompatibleMessage(message: MessageLike | null | undefined) { const rawRole = String(message?.role || "").toLowerCase(); const role = diff --git a/open-sse/services/thinkingBudget.ts b/open-sse/services/thinkingBudget.ts index d1004052de..7061bb95e0 100644 --- a/open-sse/services/thinkingBudget.ts +++ b/open-sse/services/thinkingBudget.ts @@ -224,7 +224,8 @@ function setCustomBudget(body, budget) { }; } - // OpenAI reasoning_effort mapping (T11: add 'max' tier for full budget) + // OpenAI reasoning_effort mapping. + // GPT-5/Codex accepts xhigh for the top tier; keep full budget aligned. if (result.reasoning_effort !== undefined || result.reasoning !== undefined) { if (budget <= 0) { delete result.reasoning_effort; @@ -236,7 +237,7 @@ function setCustomBudget(body, budget) { } else if (budget < 131072) { result.reasoning_effort = "high"; } else { - result.reasoning_effort = "max"; // T11: full budget → "max" + result.reasoning_effort = "xhigh"; } } diff --git a/open-sse/translator/request/claude-to-openai.ts b/open-sse/translator/request/claude-to-openai.ts index 105443eed4..8f890fd31c 100644 --- a/open-sse/translator/request/claude-to-openai.ts +++ b/open-sse/translator/request/claude-to-openai.ts @@ -5,6 +5,13 @@ import { adjustMaxTokens } from "../helpers/maxTokensHelper.ts"; type JsonRecord = Record; const TOOL_CHOICE_ANY = ["a", "n", "y"].join(""); +function normalizeOpenAIReasoningEffort(effort: unknown): string | undefined { + if (typeof effort !== "string") return undefined; + const normalized = effort.toLowerCase(); + if (normalized === "max") return "xhigh"; + return normalized || undefined; +} + // Convert Claude request to OpenAI format export function claudeToOpenAIRequest(model, body, stream) { const result: { @@ -105,8 +112,7 @@ export function claudeToOpenAIRequest(model, body, stream) { // Reasoning effort: map Claude-side thinking controls to OpenAI reasoning_effort. // Priority: output_config.effort (Claude Code) > thinking.budget_tokens (Claude native). // Budget buckets match the reverse mapping in thinkingBudget.ts::setCustomBudget. - const outputEffort = - typeof body.output_config?.effort === "string" ? body.output_config.effort.toLowerCase() : ""; + const outputEffort = normalizeOpenAIReasoningEffort(body.output_config?.effort) || ""; if (outputEffort) { result.reasoning_effort = outputEffort; } else if (body.thinking?.type === "enabled" && typeof body.thinking.budget_tokens === "number") { @@ -120,7 +126,7 @@ export function claudeToOpenAIRequest(model, body, stream) { } else if (budget < 131072) { result.reasoning_effort = "high"; } else { - result.reasoning_effort = "max"; + result.reasoning_effort = "xhigh"; } } diff --git a/open-sse/translator/request/openai-responses.ts b/open-sse/translator/request/openai-responses.ts index 5cd5da520d..d730d830e4 100644 --- a/open-sse/translator/request/openai-responses.ts +++ b/open-sse/translator/request/openai-responses.ts @@ -24,6 +24,11 @@ function toString(value: unknown, fallback = ""): string { return typeof value === "string" ? value : fallback; } +function normalizeResponsesReasoningEffort(value: unknown): string { + const effort = toString(value).toLowerCase(); + return effort === "max" ? "xhigh" : effort; +} + function unsupportedFeature(message: string): Error & { statusCode: number; errorType: string } { const error = new Error(message) as Error & { statusCode: number; errorType: string }; error.statusCode = 400; @@ -558,7 +563,7 @@ export function openaiToOpenAIResponsesRequest( if (root.reasoning !== undefined) { result.reasoning = root.reasoning; } else if (root.reasoning_effort !== undefined) { - const effort = toString(root.reasoning_effort); + const effort = normalizeResponsesReasoningEffort(root.reasoning_effort); if (effort) { result.reasoning = { effort }; } diff --git a/open-sse/utils/cursorVersionDetector.ts b/open-sse/utils/cursorVersionDetector.ts index 9ffdb524af..f42bd54fcd 100644 --- a/open-sse/utils/cursorVersionDetector.ts +++ b/open-sse/utils/cursorVersionDetector.ts @@ -12,7 +12,7 @@ import { createRequire } from "module"; const CACHE_TTL_MS = 60 * 60 * 1000; const DB_KEY = "cursorupdate.lastUpdatedAndShown.version"; -const FALLBACK_VERSION = "3.1.15"; +const FALLBACK_VERSION = "3.2.14"; let cachedVersion: string | null = null; let cachedAt = 0; diff --git a/open-sse/utils/proxyDispatcher.ts b/open-sse/utils/proxyDispatcher.ts index 07c73fad97..ecce8e184c 100644 --- a/open-sse/utils/proxyDispatcher.ts +++ b/open-sse/utils/proxyDispatcher.ts @@ -59,6 +59,20 @@ function getDispatcherOptions() { }; } +function getProxyDispatcherOptions() { + const options = getDispatcherOptions(); + // Disable keep-alive and pipelining for proxy connections. + // Cheap proxy servers aggressively drop idle sockets without sending TCP RST, + // causing "socket hang up" or "Client network socket disconnected" errors + // on subsequent requests that try to reuse the pooled connection. + return { + ...options, + keepAliveTimeout: 1, + keepAliveMaxTimeout: 1, + pipelining: 0, + }; +} + export function getDefaultDispatcher(): Dispatcher { const globalWithCache = globalThis as GlobalWithDispatcherCache; if (!globalWithCache[DEFAULT_DISPATCHER_KEY]) { @@ -74,13 +88,16 @@ export function getDefaultDispatcher(): Dispatcher { */ function extractExplicitPort(urlStr: string): string | null { try { - const idx = urlStr.indexOf('://'); + const idx = urlStr.indexOf("://"); if (idx === -1) return null; const authorityStart = idx + 3; - const authorityEnd = urlStr.indexOf('/', authorityStart); - const authority = authorityEnd === -1 ? urlStr.slice(authorityStart) : urlStr.slice(authorityStart, authorityEnd); - const lastColon = authority.lastIndexOf(':'); - const atSign = authority.lastIndexOf('@'); + const authorityEnd = urlStr.indexOf("/", authorityStart); + const authority = + authorityEnd === -1 + ? urlStr.slice(authorityStart) + : urlStr.slice(authorityStart, authorityEnd); + const lastColon = authority.lastIndexOf(":"); + const atSign = authority.lastIndexOf("@"); if (lastColon !== -1 && lastColon > atSign) { const portStr = authority.slice(lastColon + 1); if (/^\d+$/.test(portStr)) { @@ -215,7 +232,7 @@ export function proxyConfigToUrl( export function createProxyDispatcher(proxyUrl: string): Dispatcher { const normalizedUrl = normalizeProxyUrl(proxyUrl, "proxy dispatcher"); const dispatcherCache = getDispatcherCache(); - const dispatcherOptions = getDispatcherOptions(); + const proxyDispatcherOptions = getProxyDispatcherOptions(); let dispatcher = dispatcherCache.get(normalizedUrl); if (dispatcher) return dispatcher; @@ -234,12 +251,12 @@ export function createProxyDispatcher(proxyUrl: string): Dispatcher { if (parsed.password) socksOptions.password = decodeURIComponent(parsed.password); dispatcher = socksDispatcher( socksOptions as Parameters[0], - dispatcherOptions + proxyDispatcherOptions ) as Dispatcher; } else { dispatcher = new ProxyAgent({ uri: normalizedUrl, - ...dispatcherOptions, + ...proxyDispatcherOptions, }); } diff --git a/open-sse/utils/streamReadiness.ts b/open-sse/utils/streamReadiness.ts index ed3a5729ba..d73a883b08 100644 --- a/open-sse/utils/streamReadiness.ts +++ b/open-sse/utils/streamReadiness.ts @@ -31,6 +31,10 @@ function hasUsefulValue(value: unknown): boolean { "partial_json", "arguments", "name", + "thought", + "error", + "executableCode", + "codeExecutionResult", ]) { const candidate = value[key]; if (hasNonEmptyString(candidate)) return true; @@ -68,7 +72,9 @@ function hasUsefulJsonPayload(payload: unknown): boolean { if (hasUsefulValue(payload)) return true; } - return hasUsefulValue(payload.choices) || hasUsefulValue(payload.candidates) || hasUsefulValue(payload); + return ( + hasUsefulValue(payload.choices) || hasUsefulValue(payload.candidates) || hasUsefulValue(payload) + ); } export function hasUsefulStreamContent(text: string): boolean { @@ -185,7 +191,11 @@ export async function ensureStreamReadiness( `${reason} (${options.provider || "provider"}/${options.model || "unknown"})` ); await reader.cancel(reason).catch(() => {}); - return { ok: false, reason, response: createErrorResponse(HTTP_STATUS.GATEWAY_TIMEOUT, reason) }; + return { + ok: false, + reason, + response: createErrorResponse(HTTP_STATUS.GATEWAY_TIMEOUT, reason), + }; } let readResult: ReadableStreamReadResult; @@ -198,7 +208,11 @@ export async function ensureStreamReadiness( `${reason} (${options.provider || "provider"}/${options.model || "unknown"})` ); await reader.cancel(reason).catch(() => {}); - return { ok: false, reason, response: createErrorResponse(HTTP_STATUS.GATEWAY_TIMEOUT, reason) }; + return { + ok: false, + reason, + response: createErrorResponse(HTTP_STATUS.GATEWAY_TIMEOUT, reason), + }; } if (readResult.done) { @@ -207,7 +221,11 @@ export async function ensureStreamReadiness( "STREAM", `${reason} (${options.provider || "provider"}/${options.model || "unknown"})` ); - return { ok: false, reason, response: createErrorResponse(HTTP_STATUS.BAD_GATEWAY, reason) }; + return { + ok: false, + reason, + response: createErrorResponse(HTTP_STATUS.BAD_GATEWAY, reason), + }; } if (!readResult.value) continue; diff --git a/package-lock.json b/package-lock.json index 2937d025b0..dee96e1e29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "omniroute", - "version": "3.7.3", + "version": "3.7.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "omniroute", - "version": "3.7.3", + "version": "3.7.4", "hasInstallScript": true, "license": "MIT", "workspaces": [ @@ -42,6 +42,7 @@ "react": "19.2.5", "react-dom": "19.2.5", "react-is": "^19.2.5", + "react-markdown": "^10.1.0", "recharts": "^3.7.0", "selfsigned": "^5.5.0", "tls-client-node": "^0.1.13", @@ -3958,6 +3959,15 @@ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", "license": "MIT" }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", @@ -3969,9 +3979,26 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, "license": "MIT" }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/http-proxy": { "version": "1.17.17", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", @@ -4013,6 +4040,21 @@ "keytar": "*" } }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, "node_modules/@types/node": { "version": "25.6.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", @@ -4055,6 +4097,12 @@ "license": "MIT", "optional": true }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, "node_modules/@types/use-sync-external-store": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", @@ -4356,6 +4404,12 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", @@ -5205,6 +5259,16 @@ "npm": ">=6" } }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -5561,6 +5625,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", @@ -5601,6 +5675,46 @@ "node": ">=8" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -5782,6 +5896,16 @@ "node": ">= 0.8" } }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -6196,6 +6320,19 @@ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", "license": "MIT" }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -6325,7 +6462,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -6340,6 +6476,19 @@ "node": ">=8" } }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -7184,6 +7333,16 @@ "node": ">=4.0" } }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -7320,6 +7479,12 @@ "express": ">= 4.11" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, "node_modules/fast-copy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-4.0.2.tgz", @@ -8026,6 +8191,46 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/help-me": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", @@ -8093,6 +8298,16 @@ "dev": true, "license": "MIT" }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -8292,6 +8507,12 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -8344,6 +8565,30 @@ "node": ">= 0.10" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -8507,6 +8752,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-docker": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", @@ -8595,6 +8850,16 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-in-ssh": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz", @@ -8695,6 +8960,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -9665,6 +9942,16 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -9751,6 +10038,159 @@ "node": ">= 0.4" } }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdn-data": { "version": "2.27.1", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", @@ -9789,6 +10229,448 @@ "node": ">= 8" } }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -10468,6 +11350,31 @@ "node": ">=6" } }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -10903,6 +11810,16 @@ "dev": true, "license": "MIT" }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -11080,6 +11997,33 @@ "integrity": "sha512-Dn0t8IQhCmeIT3wu+Apm1/YVsJXsGWi6k4sPdnBIdqMVtHtv0IGi6dcpNpNkNac0zB2uUAqNX3MHzN8c+z2rwQ==", "license": "MIT" }, + "node_modules/react-markdown": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, "node_modules/react-redux": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", @@ -11251,6 +12195,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -12005,6 +12982,16 @@ "node": ">=0.10.0" } }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -12236,6 +13223,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/strip-ansi": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", @@ -12299,6 +13300,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, "node_modules/styled-jsx": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", @@ -12620,6 +13639,26 @@ "tree-kill": "cli.js" } }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/ts-api-utils": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", @@ -12905,6 +13944,93 @@ "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", "license": "MIT" }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -13079,6 +14205,34 @@ "node": ">= 0.8" } }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/victory-vendor": { "version": "37.3.6", "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", @@ -13806,9 +14960,19 @@ } } }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "open-sse": { "name": "@omniroute/open-sse", - "version": "3.7.3" + "version": "3.7.4" } } } diff --git a/package.json b/package.json index a077aadc94..e17f1e9d4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "omniroute", - "version": "3.7.3", + "version": "3.7.4", "description": "Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.", "type": "module", "bin": { @@ -136,6 +136,7 @@ "react": "19.2.5", "react-dom": "19.2.5", "react-is": "^19.2.5", + "react-markdown": "^10.1.0", "recharts": "^3.7.0", "selfsigned": "^5.5.0", "tls-client-node": "^0.1.13", diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4a0d1407f0f0db9dc10e3310d0c8893681cc5a GIT binary patch literal 7230 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 E0>SdMVE_OC literal 0 HcmV?d00001 diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1b6fbae4f347500cfaa64a8a81ca14027b1995d6 GIT binary patch literal 141845 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 E0>SdMVE_OC literal 0 HcmV?d00001 diff --git a/public/sw.js b/public/sw.js new file mode 100644 index 0000000000..eaa1d86398 --- /dev/null +++ b/public/sw.js @@ -0,0 +1,77 @@ +const CACHE_NAME = "omniroute-pwa-v1"; +const APP_SHELL = [ + "/", + "/offline", + "/manifest.webmanifest", + "/icon-512.png", + "/apple-touch-icon.png", +]; +const EXCLUDED_PATH_PREFIXES = ["/api/", "/a2a", "/dashboard/endpoint"]; + +self.addEventListener("install", (event) => { + event.waitUntil( + caches + .open(CACHE_NAME) + .then((cache) => cache.addAll(APP_SHELL)) + .then(() => self.skipWaiting()) + ); +}); + +self.addEventListener("activate", (event) => { + event.waitUntil( + caches + .keys() + .then((keys) => + Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key))) + ) + .then(() => self.clients.claim()) + ); +}); + +self.addEventListener("fetch", (event) => { + if (event.request.method !== "GET") { + return; + } + + const requestUrl = new URL(event.request.url); + const isSameOrigin = requestUrl.origin === self.location.origin; + const isExcludedPath = EXCLUDED_PATH_PREFIXES.some((prefix) => + requestUrl.pathname.startsWith(prefix) + ); + const destination = event.request.destination; + const isStaticAsset = ["style", "script", "image", "font"].includes(destination); + const isNavigateRequest = event.request.mode === "navigate"; + + // Never cache API/dashboard traffic with potentially auth-sensitive content. + if (!isSameOrigin || isExcludedPath) { + return; + } + + event.respondWith( + (async () => { + if (isNavigateRequest) { + try { + return await fetch(event.request); + } catch { + return (await caches.match("/offline")) || Response.error(); + } + } + + if (!isStaticAsset) { + return fetch(event.request); + } + + const cachedResponse = await caches.match(event.request); + if (cachedResponse) { + return cachedResponse; + } + + const networkResponse = await fetch(event.request); + if (networkResponse && networkResponse.status === 200) { + const responseClone = networkResponse.clone(); + void caches.open(CACHE_NAME).then((cache) => cache.put(event.request, responseClone)); + } + return networkResponse; + })() + ); +}); diff --git a/src/app/(dashboard)/dashboard/HomePageClient.tsx b/src/app/(dashboard)/dashboard/HomePageClient.tsx index adf7b079e2..6c3a7b18de 100644 --- a/src/app/(dashboard)/dashboard/HomePageClient.tsx +++ b/src/app/(dashboard)/dashboard/HomePageClient.tsx @@ -12,6 +12,7 @@ import ProviderIcon from "@/shared/components/ProviderIcon"; import { AI_PROVIDERS, FREE_PROVIDERS, OAUTH_PROVIDERS } from "@/shared/constants/providers"; import { useNotificationStore } from "@/store/notificationStore"; import { copyToClipboard } from "@/shared/utils/clipboard"; +import type { NewsAnnouncement } from "@/shared/utils/releaseNotes"; type UpdateStep = { step: string; @@ -19,6 +20,16 @@ type UpdateStep = { message: string; }; +type VersionInfo = { + current: string; + latest: string; + updateAvailable: boolean; + channel: string; + autoUpdateSupported: boolean; + autoUpdateError?: string | null; + news?: NewsAnnouncement | null; +}; + const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); function mergeUpdateStep(steps: UpdateStep[], nextStep: UpdateStep) { @@ -43,7 +54,7 @@ export default function HomePageClient({ machineId }) { const [selectedProvider, setSelectedProvider] = useState(null); const [providerMetrics, setProviderMetrics] = useState({}); - const [versionInfo, setVersionInfo] = useState(null); + const [versionInfo, setVersionInfo] = useState(null); const [updating, setUpdating] = useState(false); const [updateSteps, setUpdateSteps] = useState([]); const [updatePhase, setUpdatePhase] = useState<"idle" | "running" | "done" | "failed">("idle"); @@ -540,29 +551,64 @@ export default function HomePageClient({ machineId }) { {/* Update Notification Banner */} {versionInfo?.updateAvailable && !showUpdateOverlay && ( -
-
- system_update_alt -
-

Update Available: v{versionInfo.latest}

-

- {versionInfo.autoUpdateSupported - ? t("updateAvailableDesc") || - `You are currently using v${versionInfo.current}. Update to access the latest features and bug fixes.` - : versionInfo.autoUpdateError || - "Manual update required for this installation type."} -

+
+
+
+ + system_update_alt + +
+

Update Available: v{versionInfo.latest}

+

+ {versionInfo.autoUpdateSupported + ? t("updateAvailableDesc") || + `You are currently using v${versionInfo.current}. Update to access the latest features and bug fixes.` + : versionInfo.autoUpdateError || + "Manual update required for this installation type."} +

+
+
- + + {/* News Notification Banner */} + {versionInfo?.news && ( +
+
+
+ + {versionInfo.news.icon || "campaign"} + +
+
+

{versionInfo.news.title}

+

+ {versionInfo.news.message} +

+
+
+ + {versionInfo.news.link && ( + + {versionInfo.news.linkLabel || "Ler Mais"} + arrow_forward + + )} +
+ )}
)} diff --git a/src/app/(dashboard)/dashboard/agents/page.tsx b/src/app/(dashboard)/dashboard/agents/page.tsx index 84dfc56d57..74dc2ff90d 100644 --- a/src/app/(dashboard)/dashboard/agents/page.tsx +++ b/src/app/(dashboard)/dashboard/agents/page.tsx @@ -6,7 +6,12 @@ import { Card, Button, Input } from "@/shared/components"; import ProviderIcon from "@/shared/components/ProviderIcon"; import { useTranslations } from "next-intl"; import { AI_PROVIDERS } from "@/shared/constants/providers"; -import { CLI_COMPAT_PROVIDER_IDS } from "@/shared/constants/cliCompatProviders"; +import { CLI_TOOLS } from "@/shared/constants/cliTools"; +import { + CLI_COMPAT_PROVIDER_IDS, + CLI_COMPAT_TOGGLE_IDS, + normalizeCliCompatProviderId, +} from "@/shared/constants/cliCompatProviders"; interface AgentInfo { id: string; @@ -106,6 +111,14 @@ export default function AgentsPage() { } }; + const normalizedCliCompatProviders = Array.from( + new Set( + (settings.cliCompatProviders || []) + .map((providerId: string) => normalizeCliCompatProviderId(providerId)) + .filter((providerId: string) => CLI_COMPAT_PROVIDER_IDS.includes(providerId)) + ) + ); + const handleRefresh = async () => { setRefreshing(true); try { @@ -307,19 +320,19 @@ export default function AgentsPage() {

{ts("cliFingerprintDesc")}

- {CLI_COMPAT_PROVIDER_IDS.map((providerId) => { - const providerMeta = Object.values(AI_PROVIDERS).find( - (p: any) => p.id === providerId - ) as any; - const isEnabled = (settings.cliCompatProviders || []).includes(providerId); - const displayName = providerMeta?.name || providerId; + {CLI_COMPAT_TOGGLE_IDS.map((toggleId) => { + const providerId = normalizeCliCompatProviderId(toggleId); + const providerMeta = Object.values(AI_PROVIDERS).find((p: any) => p.id === providerId) as any; + const toolMeta = CLI_TOOLS[toggleId as keyof typeof CLI_TOOLS] as any; + const isEnabled = normalizedCliCompatProviders.includes(providerId); + const displayName = toolMeta?.name || providerMeta?.name || toggleId; const icon = providerMeta?.icon || "terminal"; const color = providerMeta?.color || "#888"; return (
- {(settings.cliCompatProviders || []).length > 0 && ( + {normalizedCliCompatProviders.length > 0 && (

verified {ts("cliFingerprintEnabled", { - count: (settings.cliCompatProviders || []).length, + count: normalizedCliCompatProviders.length, })}

)} diff --git a/src/app/(dashboard)/dashboard/changelog/components/ChangelogViewer.tsx b/src/app/(dashboard)/dashboard/changelog/components/ChangelogViewer.tsx new file mode 100644 index 0000000000..be6f89bc85 --- /dev/null +++ b/src/app/(dashboard)/dashboard/changelog/components/ChangelogViewer.tsx @@ -0,0 +1,146 @@ +"use client"; + +import { useEffect, useState } from "react"; +import ReactMarkdown, { type Components } from "react-markdown"; +import { Button } from "@/shared/components"; +import { + CHANGELOG_GITHUB_URL, + CHANGELOG_RAW_URL, + getLatestChangelogMarkdown, +} from "@/shared/utils/releaseNotes"; + +function resolveChangelogHref(href: string | undefined): string | null { + if (!href) return null; + if (href.startsWith("#")) return href; + + try { + const url = new URL(href, "https://github.com/diegosouzapw/OmniRoute/blob/main/"); + return url.protocol === "https:" ? url.toString() : null; + } catch { + return null; + } +} + +const markdownComponents: Components = { + h1({ children }) { + return

{children}

; + }, + h2({ children }) { + return ( +

+ sell + {children} +

+ ); + }, + h3({ children }) { + return ( +

{children}

+ ); + }, + p({ children }) { + return

{children}

; + }, + ul({ children }) { + return
    {children}
; + }, + li({ children }) { + return ( +
  • + + {children} +
  • + ); + }, + strong({ children }) { + return {children}; + }, + code({ children }) { + return ( + + {children} + + ); + }, + a({ href, children }) { + const resolvedHref = resolveChangelogHref(href); + if (!resolvedHref) return {children}; + + return ( + + {children} + + ); + }, +}; + +export default function ChangelogViewer() { + const [markdown, setMarkdown] = useState(""); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + + useEffect(() => { + async function fetchChangelog() { + try { + const res = await fetch(CHANGELOG_RAW_URL, { cache: "no-store" }); + if (!res.ok) throw new Error(`Changelog fetch failed with ${res.status}`); + + const text = await res.text(); + setMarkdown(getLatestChangelogMarkdown(text, 10)); + } catch (err) { + console.error(err); + setError(true); + } finally { + setLoading(false); + } + } + + fetchChangelog(); + }, []); + + if (loading) { + return ( +
    + + sync + +

    Loading changelog from GitHub...

    +
    + ); + } + + if (error) { + return ( +
    + + error_outline + +

    Could not load the changelog. Please try again later.

    + +
    + ); + } + + return ( + + ); +} diff --git a/src/app/(dashboard)/dashboard/changelog/components/NewsViewer.tsx b/src/app/(dashboard)/dashboard/changelog/components/NewsViewer.tsx new file mode 100644 index 0000000000..0910bd056b --- /dev/null +++ b/src/app/(dashboard)/dashboard/changelog/components/NewsViewer.tsx @@ -0,0 +1,95 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { Button } from "@/shared/components"; +import { + NEWS_JSON_URL, + parseActiveNewsPayload, + type NewsAnnouncement, +} from "@/shared/utils/releaseNotes"; + +export default function NewsViewer() { + const [news, setNews] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + + useEffect(() => { + async function fetchNews() { + try { + const res = await fetch(NEWS_JSON_URL, { cache: "no-store" }); + if (res.ok) { + const data = await res.json(); + setNews(parseActiveNewsPayload(data)); + } else { + setError(true); + } + } catch (err) { + console.error("Failed to fetch news:", err); + setError(true); + } finally { + setLoading(false); + } + } + fetchNews(); + }, []); + + if (loading) { + return ( +
    + + sync + +
    + ); + } + + if (error) { + return ( +
    + + error_outline + +

    Could not load announcements. Please try again later.

    +
    + ); + } + + if (!news || !news.active) { + return ( +
    + + notifications_off + +

    No new announcements at this time.

    +
    + ); + } + + return ( +
    +
    +
    + + {news.icon || "campaign"} + +
    + +
    +

    {news.title}

    +

    {news.message}

    +
    + + {news.link && ( + + )} +
    +
    + ); +} diff --git a/src/app/(dashboard)/dashboard/changelog/page.tsx b/src/app/(dashboard)/dashboard/changelog/page.tsx new file mode 100644 index 0000000000..d467f00f27 --- /dev/null +++ b/src/app/(dashboard)/dashboard/changelog/page.tsx @@ -0,0 +1,40 @@ +"use client"; + +import { useState } from "react"; +import { useTranslations } from "next-intl"; +import { Card, SegmentedControl } from "@/shared/components"; +import ChangelogViewer from "./components/ChangelogViewer"; +import NewsViewer from "./components/NewsViewer"; + +export default function ChangelogPage() { + const [activeTab, setActiveTab] = useState<"news" | "changelog">("news"); + const t = useTranslations("sidebar"); + const title = typeof t.has === "function" && t.has("changelog") ? t("changelog") : "Changelog"; + + return ( +
    +
    +
    +

    {title}

    +

    + Stay up to date with the latest platform features and announcements. +

    +
    +
    + setActiveTab(val as "news" | "changelog")} + /> +
    +
    + + + {activeTab === "news" ? : } + +
    + ); +} diff --git a/src/app/(dashboard)/dashboard/cli-tools/components/ClaudeToolCard.tsx b/src/app/(dashboard)/dashboard/cli-tools/components/ClaudeToolCard.tsx index 20ae5ad1e3..6ecd322bac 100644 --- a/src/app/(dashboard)/dashboard/cli-tools/components/ClaudeToolCard.tsx +++ b/src/app/(dashboard)/dashboard/cli-tools/components/ClaudeToolCard.tsx @@ -5,6 +5,10 @@ import { Card, Button, ModelSelectModal, ManualConfigModal } from "@/shared/comp import Image from "next/image"; import CliStatusBadge from "./CliStatusBadge"; import { useTranslations } from "next-intl"; +import { + getStoredClaudeAuthValue, + normalizeClaudeBaseUrl, +} from "@/shared/services/claudeCliConfig"; const CLOUD_URL = process.env.NEXT_PUBLIC_CLOUD_URL; @@ -98,7 +102,7 @@ export default function ClaudeToolCard({ } }); // Restore selected key from file: match token stored in file against known keys - const tokenFromFile = env.ANTHROPIC_AUTH_TOKEN; + const tokenFromFile = getStoredClaudeAuthValue(env); if (tokenFromFile) { // (#523) Keys from /api/keys are masked (first 8 + "****" + last 4). // Mask the token from file to compare against the masked list. @@ -124,12 +128,12 @@ export default function ClaudeToolCard({ const getEffectiveBaseUrl = () => { const url = customBaseUrl || baseUrl; - return url.endsWith("/v1") ? url : `${url}/v1`; + return normalizeClaudeBaseUrl(url); }; const getDisplayUrl = () => { const url = customBaseUrl || baseUrl; - return url.endsWith("/v1") ? url : `${url}/v1`; + return normalizeClaudeBaseUrl(url); }; const handleApplySettings = async () => { @@ -139,13 +143,9 @@ export default function ClaudeToolCard({ const env: any = { ANTHROPIC_BASE_URL: getEffectiveBaseUrl() }; // (#523) Prefer keyId lookup so the backend writes the real key to disk. - // Fall back to sk_omniroute for localhost-only setups without a key. + // If no key is selected, leave auth unset so local installs can rely on + // anonymous access instead of persisting a fake placeholder token. const selectedKeyId = selectedApiKey?.trim() || (apiKeys?.length > 0 ? apiKeys[0].id : null); - const skOmnirouteFallback = !cloudEnabled ? "sk_omniroute" : null; - - if (!selectedKeyId && skOmnirouteFallback) { - env.ANTHROPIC_AUTH_TOKEN = skOmnirouteFallback; - } tool.defaultModels.forEach((model) => { const targetModel = modelMappings[model.alias] || model.defaultValue || ""; @@ -221,13 +221,13 @@ export default function ClaudeToolCard({ // Generate settings.json content for manual copy const getManualConfigs = () => { - const keyToUse = - selectedApiKey && selectedApiKey.trim() - ? selectedApiKey - : !cloudEnabled - ? "sk_omniroute" - : ""; - const env = { ANTHROPIC_BASE_URL: getEffectiveBaseUrl(), ANTHROPIC_AUTH_TOKEN: keyToUse }; + const env = { ANTHROPIC_BASE_URL: getEffectiveBaseUrl() }; + if (selectedApiKey && selectedApiKey.trim()) { + env.ANTHROPIC_AUTH_TOKEN = ""; + } else if (cloudEnabled) { + env.ANTHROPIC_AUTH_TOKEN = ""; + } + tool.defaultModels.forEach((model) => { const targetModel = modelMappings[model.alias]; if (targetModel && model.envKey) env[model.envKey] = targetModel; @@ -443,7 +443,7 @@ export default function ClaudeToolCard({ ) : ( - {cloudEnabled ? t("noApiKeysCreateOne") : t("defaultOmnirouteKey")} + {cloudEnabled ? t("noApiKeysCreateOne") : t("noApiKeysAvailable")} )}
    diff --git a/src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.tsx b/src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.tsx index cd14821237..d07926b240 100644 --- a/src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.tsx +++ b/src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.tsx @@ -103,6 +103,8 @@ export default function APIPageClient({ machineId }) { const [tailscaleInstallBusy, setTailscaleInstallBusy] = useState(false); const [tailscaleInstallLog, setTailscaleInstallLog] = useState([]); const [tailscalePassword, setTailscalePassword] = useState(""); + const [showCloudflaredTunnel, setShowCloudflaredTunnel] = useState(true); + const [showTailscaleFunnel, setShowTailscaleFunnel] = useState(true); const { copied, copy } = useCopyToClipboard(); @@ -308,6 +310,8 @@ export default function APIPageClient({ machineId }) { if (data.machineId) { setResolvedMachineId(data.machineId); } + setShowCloudflaredTunnel(data.hideEndpointCloudflaredTunnel !== true); + setShowTailscaleFunnel(data.hideEndpointTailscaleFunnel !== true); } } catch (error) { console.log("Error loading cloud settings:", error); @@ -989,236 +993,242 @@ export default function APIPageClient({ machineId }) {
    -
    -
    -
    -
    -
    -

    - {translateOrFallback("cloudflaredTitle", "Cloudflare Quick Tunnel")} -

    - - {cloudflaredPhaseMeta[cloudflaredPhase].label} - + {showCloudflaredTunnel && ( +
    +
    +
    +
    +
    +

    + {translateOrFallback("cloudflaredTitle", "Cloudflare Quick Tunnel")} +

    + + {cloudflaredPhaseMeta[cloudflaredPhase].label} + +
    -
    - {cloudflaredStatus?.supported !== false && ( - - )} -
    - - {cloudflaredNotice && ( -
    - - {cloudflaredNotice.type === "success" - ? "check_circle" - : cloudflaredNotice.type === "info" - ? "info" - : "error"} - - {cloudflaredNotice.message} - -
    - )} - -

    {cloudflaredUrlNotice}

    -
    - - -
    - {cloudflaredStatus?.lastError && ( -

    - {translateOrFallback("cloudflaredLastError", "Last error: {error}", { - error: cloudflaredStatus.lastError, - })} -

    - )} -
    -
    - -
    -
    -
    -
    -
    -

    - {translateOrFallback("tailscaleTitle", "Tailscale Funnel")} -

    - - {tailscalePhaseMeta[tailscalePhase].label} - -
    -
    - - {tailscaleStatus?.supported !== false && ( - - )} -
    - - {tailscaleNotice && ( -
    - - {tailscaleNotice.type === "success" - ? "check_circle" - : tailscaleNotice.type === "info" - ? "info" - : "error"} - - {tailscaleNotice.message} - -
    - )} - -

    {tailscaleUrlNotice}

    - {tailscaleStatus?.phase === "needs_login" && ( -

    - {translateOrFallback( - "tailscaleNeedsLoginHint", - "Authenticate this machine with Tailscale, then enable Funnel." + loading={cloudflaredBusy} + className={ + cloudflaredStatus?.running + ? "border-border/70! text-text-muted! hover:text-text!" + : "bg-linear-to-r from-primary to-cyan-500 hover:from-primary-hover hover:to-cyan-600" + } + > + {cloudflaredActionLabel} + )} -

    - )} - {/* Sudo password input — shown when Tailscale is installed but not running (needs sudo to start daemon) */} - {tailscaleStatus?.installed && - !tailscaleStatus?.running && - tailscaleStatus?.platform !== "win32" && ( -
    - - setTailscalePassword(event.target.value)} - placeholder={translateOrFallback( - "tailscaleSudoPlaceholder", - "Enter sudo password" - )} - disabled={tailscaleBusy} - className="font-mono text-sm" - /> +
    + + {cloudflaredNotice && ( +
    + + {cloudflaredNotice.type === "success" + ? "check_circle" + : cloudflaredNotice.type === "info" + ? "info" + : "error"} + + {cloudflaredNotice.message} +
    )} -
    - - + +

    {cloudflaredUrlNotice}

    +
    + + +
    + {cloudflaredStatus?.lastError && ( +

    + {translateOrFallback("cloudflaredLastError", "Last error: {error}", { + error: cloudflaredStatus.lastError, + })} +

    + )}
    - {tailscaleStatus?.binaryPath && ( -

    - {translateOrFallback("tailscaleBinaryPath", "Binary: {path}", { - path: tailscaleStatus.binaryPath, - })} -

    - )} - {tailscaleStatus?.lastError && ( -

    - {translateOrFallback("tailscaleLastError", "Last error: {error}", { - error: tailscaleStatus.lastError, - })} -

    - )}
    -
    + )} + + {showTailscaleFunnel && ( +
    +
    +
    +
    +
    +

    + {translateOrFallback("tailscaleTitle", "Tailscale Funnel")} +

    + + {tailscalePhaseMeta[tailscalePhase].label} + +
    +
    + + {tailscaleStatus?.supported !== false && ( + + )} +
    + + {tailscaleNotice && ( +
    + + {tailscaleNotice.type === "success" + ? "check_circle" + : tailscaleNotice.type === "info" + ? "info" + : "error"} + + {tailscaleNotice.message} + +
    + )} + +

    {tailscaleUrlNotice}

    + {tailscaleStatus?.phase === "needs_login" && ( +

    + {translateOrFallback( + "tailscaleNeedsLoginHint", + "Authenticate this machine with Tailscale, then enable Funnel." + )} +

    + )} + {/* Sudo password input — shown when Tailscale is installed but not running (needs sudo to start daemon) */} + {tailscaleStatus?.installed && + !tailscaleStatus?.running && + tailscaleStatus?.platform !== "win32" && ( +
    + + setTailscalePassword(event.target.value)} + placeholder={translateOrFallback( + "tailscaleSudoPlaceholder", + "Enter sudo password" + )} + disabled={tailscaleBusy} + className="font-mono text-sm" + /> +
    + )} +
    + + +
    + {tailscaleStatus?.binaryPath && ( +

    + {translateOrFallback("tailscaleBinaryPath", "Binary: {path}", { + path: tailscaleStatus.binaryPath, + })} +

    + )} + {tailscaleStatus?.lastError && ( +

    + {translateOrFallback("tailscaleLastError", "Last error: {error}", { + error: tailscaleStatus.lastError, + })} +

    + )} +
    +
    + )} diff --git a/src/app/(dashboard)/dashboard/providers/[id]/page.tsx b/src/app/(dashboard)/dashboard/providers/[id]/page.tsx index cdcfa5dfdd..25ad3c7f7b 100644 --- a/src/app/(dashboard)/dashboard/providers/[id]/page.tsx +++ b/src/app/(dashboard)/dashboard/providers/[id]/page.tsx @@ -2730,7 +2730,7 @@ export default function ProviderDetailPage() { {isCompatible && providerNode && ( -
    +

    {isCcCompatible @@ -2743,7 +2743,7 @@ export default function ProviderDetailPage() { {getApiLabel()} · {(providerNode.baseUrl || "").replace(/\/$/, "")}/{getApiPath()}

    -
    +
    @@ -2788,6 +2788,16 @@ export default function ProviderDetailPage() {
    + {isCcCompatible && ( +
    +
    + + warning + +

    {t("ccCompatibleValidationHint")}

    +
    +
    + )} )} @@ -3525,12 +3535,12 @@ function ModelRow({ className={`rounded p-0.5 hover:bg-sidebar transition-colors disabled:opacity-40 disabled:cursor-not-allowed ${testStatus === "ok" ? "text-green-500" : testStatus === "error" ? "text-red-500" : "text-text-muted hover:text-primary"}`} title={ testingModel - ? t("testingModel", "Testing...") + ? t("testingModel") : testStatus === "ok" ? "OK" : testStatus === "error" ? "Error" - : t("testModel", "Test Model") + : t("testModel") } > {testingModel ? ( @@ -3911,12 +3921,12 @@ function PassthroughModelRow({ className={`rounded p-0.5 hover:bg-sidebar transition-colors disabled:opacity-40 disabled:cursor-not-allowed ${testStatus === "ok" ? "text-green-500" : testStatus === "error" ? "text-red-500" : "text-text-muted hover:text-primary"}`} title={ testingModel - ? t("testingModel", "Testing...") + ? t("testingModel") : testStatus === "ok" ? "OK" : testStatus === "error" ? "Error" - : t("testModel", "Test Model") + : t("testModel") } > {testingModel ? ( @@ -5772,6 +5782,7 @@ function AddApiKeyModal({ } let isValid = false; + let validationError: string | null = null; try { setValidating(true); setValidationResult(null); @@ -5789,6 +5800,9 @@ function AddApiKeyModal({ }); const data = await res.json(); isValid = !!data.valid; + if (!isValid && data.error) { + validationError = data.error; + } setValidationResult(isValid ? "success" : "failed"); } catch { setValidationResult("failed"); @@ -5797,8 +5811,13 @@ function AddApiKeyModal({ } if (!isValid) { - setSaveError(t("apiKeyValidationFailed")); - return; + if (apiKeyOptional && !formData.apiKey) { + // Bypass validation block for local/optional providers when no key is provided + console.debug("Validation failed but apiKey is optional; proceeding to save."); + } else { + setSaveError(validationError || t("apiKeyValidationFailed")); + return; + } } const providerSpecificData: Record = {}; @@ -5860,6 +5879,16 @@ function AddApiKeyModal({ onClose={onClose} >
    + {isCcCompatible && ( +
    +
    + + warning + +

    {t("ccCompatibleValidationHint")}

    +
    +
    + )}
    )} - {isCompatible && ( + {isCompatible && !isCcCompatible && (

    - {isCcCompatible - ? t("ccCompatibleValidationHint") - : isAnthropic - ? t("validationChecksAnthropicCompatible", { - provider: providerName || t("anthropicCompatibleName"), - }) - : t("validationChecksOpenAiCompatible", { - provider: providerName || t("openaiCompatibleName"), - })} + {isAnthropic + ? t("validationChecksAnthropicCompatible", { + provider: providerName || t("anthropicCompatibleName"), + }) + : t("validationChecksOpenAiCompatible", { + provider: providerName || t("openaiCompatibleName"), + })}

    )}
    )} @@ -1896,7 +1907,7 @@ function AddCcCompatibleModal({ isOpen, addLabel, compatibleLabel, onClose, onCr
    +
    +
    +

    + {getSettingsLabel("endpointTunnelVisibility", "Endpoint tunnel visibility")} +

    +

    + {getSettingsLabel( + "endpointTunnelVisibilityDesc", + "Hide tunnel controls from the Endpoint page without changing tunnel state." + )} +

    +
    + +
    +
    +
    +

    + {getSettingsLabel("showCloudflareTunnel", "Cloudflare Quick Tunnel")} +

    +

    + {getSettingsLabel( + "showCloudflareTunnelDesc", + "Show Cloudflare Quick Tunnel controls on the Endpoint page." + )} +

    +
    + updateSetting("hideEndpointCloudflaredTunnel", !checked)} + disabled={loading} + /> +
    + +
    +
    +

    + {getSettingsLabel("showTailscaleFunnel", "Tailscale Funnel")} +

    +

    + {getSettingsLabel( + "showTailscaleFunnelDesc", + "Show Tailscale Funnel controls on the Endpoint page." + )} +

    +
    + updateSetting("hideEndpointTailscaleFunnel", !checked)} + disabled={loading} + /> +
    +
    +
    +

    diff --git a/src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx b/src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx index b673d92f22..14b3610a67 100644 --- a/src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx @@ -38,6 +38,23 @@ type TestResult = { error?: string; }; +type ParsedProxyEntry = { + name: string; + host: string; + port: number; + username: string; + password: string; + type: string; + region: string; + status: string; + notes: string; +}; + +type ParseError = { + line: number; + reason: string; +}; + const EMPTY_FORM = { id: "", name: "", @@ -51,6 +68,85 @@ const EMPTY_FORM = { status: "active", }; +const BULK_IMPORT_TEMPLATE = `# Proxy Bulk Import +# Format: NAME|HOST|PORT|USERNAME|PASSWORD|TYPE|REGION|STATUS|NOTES +# Required: NAME, HOST, PORT +# Optional: USERNAME, PASSWORD, TYPE (http|https|socks5, default: socks5), REGION, STATUS (active|inactive, default: active), NOTES +# Lines starting with # are ignored. Existing proxies (same host+port) will be updated. +# +# SOCKS5 examples: +# proxy-us|138.99.147.218|50101|myuser|mypass|socks5|US-East|active|US production proxy +# proxy-eu|200.234.177.62|50101|myuser|mypass|socks5|EU-West +# +# HTTP/HTTPS examples: +# http-proxy|10.0.0.50|8080|||http||active|Internal HTTP proxy +# https-proxy|proxy.example.com|443|admin|secret123|https|US|active +`; + +const VALID_TYPES = new Set(["http", "https", "socks5"]); +const VALID_STATUSES = new Set(["active", "inactive"]); + +function parseBulkImportText(text: string): { + entries: ParsedProxyEntry[]; + errors: ParseError[]; + skipped: number; +} { + const lines = text.split("\n"); + const entries: ParsedProxyEntry[] = []; + const errors: ParseError[] = []; + let skipped = 0; + + for (let i = 0; i < lines.length; i++) { + const raw = lines[i].trim(); + if (!raw || raw.startsWith("#")) { + skipped++; + continue; + } + + const parts = raw.split("|").map((p) => p.trim()); + const [name, host, portStr, username, password, type, region, status, notes] = parts; + const lineNum = i + 1; + + if (!name) { + errors.push({ line: lineNum, reason: "Missing NAME" }); + continue; + } + if (!host) { + errors.push({ line: lineNum, reason: "Missing HOST" }); + continue; + } + const port = Number(portStr); + if (!portStr || isNaN(port) || port < 1 || port > 65535) { + errors.push({ line: lineNum, reason: "Invalid PORT (must be 1-65535)" }); + continue; + } + const normalizedType = (type || "socks5").toLowerCase(); + if (!VALID_TYPES.has(normalizedType)) { + errors.push({ line: lineNum, reason: `Invalid TYPE '${type}' (use http, https, or socks5)` }); + continue; + } + const normalizedStatus = (status || "active").toLowerCase(); + if (!VALID_STATUSES.has(normalizedStatus)) { + errors.push({ line: lineNum, reason: `Invalid STATUS '${status}' (use active or inactive)` }); + continue; + } + + entries.push({ + name, + host, + port, + username: username || "", + password: password || "", + type: normalizedType, + region: region || "", + status: normalizedStatus, + notes: notes || "", + }); + } + + return { entries, errors, skipped }; +} + export default function ProxyRegistryManager() { const t = useTranslations("proxyRegistry"); const [items, setItems] = useState([]); @@ -72,6 +168,20 @@ export default function ProxyRegistryManager() { const [bulkScopeIds, setBulkScopeIds] = useState(""); const [bulkProxyId, setBulkProxyId] = useState(""); + // Bulk Import state + const [bulkImportOpen, setBulkImportOpen] = useState(false); + const [bulkImportText, setBulkImportText] = useState(BULK_IMPORT_TEMPLATE); + const [bulkImportParsed, setBulkImportParsed] = useState([]); + const [bulkImportErrors, setBulkImportErrors] = useState([]); + const [bulkImportSkipped, setBulkImportSkipped] = useState(0); + const [bulkImportParsedOnce, setBulkImportParsedOnce] = useState(false); + const [bulkImporting, setBulkImporting] = useState(false); + const [bulkImportResult, setBulkImportResult] = useState<{ + created: number; + updated: number; + failed: number; + } | null>(null); + const editingId = useMemo(() => form.id || "", [form.id]); const loadHealth = useCallback(async () => { @@ -382,6 +492,77 @@ export default function ProxyRegistryManager() { } }; + const handleBulkImportParse = () => { + const { entries, errors, skipped } = parseBulkImportText(bulkImportText); + setBulkImportParsed(entries); + setBulkImportErrors(errors); + setBulkImportSkipped(skipped); + setBulkImportParsedOnce(true); + setBulkImportResult(null); + }; + + const handleBulkImportExecute = async () => { + if (bulkImportParsed.length === 0) return; + if (bulkImportParsed.length > 100) { + setError(t("bulkImportMaxExceeded")); + return; + } + + setBulkImporting(true); + setError(null); + setBulkImportResult(null); + + try { + const payload = { + items: bulkImportParsed.map((entry) => ({ + name: entry.name, + type: entry.type, + host: entry.host, + port: entry.port, + username: entry.username || undefined, + password: entry.password || undefined, + region: entry.region || null, + notes: entry.notes || null, + status: entry.status as "active" | "inactive", + })), + }; + + const res = await fetch("/api/settings/proxies/bulk-import", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + }); + const data = await res.json().catch(() => ({})); + + if (!res.ok) { + setError(data?.error?.message || "Failed to import proxies"); + return; + } + + setBulkImportResult({ + created: data.created || 0, + updated: data.updated || 0, + failed: data.failed || 0, + }); + + await load(); + } catch (e: any) { + setError(e?.message || "Failed to import proxies"); + } finally { + setBulkImporting(false); + } + }; + + const openBulkImport = () => { + setBulkImportText(BULK_IMPORT_TEMPLATE); + setBulkImportParsed([]); + setBulkImportErrors([]); + setBulkImportSkipped(0); + setBulkImportParsedOnce(false); + setBulkImportResult(null); + setBulkImportOpen(true); + }; + return ( <> @@ -401,6 +582,15 @@ export default function ProxyRegistryManager() { > {t("importLegacy")} +

    + + {/* Bulk Import Modal */} + { + if (!bulkImporting) setBulkImportOpen(false); + }} + title={t("bulkImportTitle")} + maxWidth="xl" + > +
    +

    {t("bulkImportDescription")}

    + +
    +